2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
57 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
59 #define D3DCREATEOBJECTINSTANCE(object, type) { \
60 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
61 D3DMEMCHECK(object, pp##type); \
62 object->lpVtbl = &IWineD3D##type##_Vtbl; \
63 object->wineD3DDevice = This; \
64 object->parent = parent; \
66 *pp##type = (IWineD3D##type *) object; \
69 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
70 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
71 D3DMEMCHECK(object, pp##type); \
72 object->lpVtbl = &IWineD3D##type##_Vtbl; \
73 object->resource.wineD3DDevice = This; \
74 object->resource.parent = parent; \
75 object->resource.resourceType = d3dtype; \
76 object->resource.ref = 1; \
77 object->resource.pool = Pool; \
78 object->resource.format = Format; \
79 object->resource.usage = Usage; \
80 object->resource.size = _size; \
81 /* Check that we have enough video ram left */ \
82 if (Pool == D3DPOOL_DEFAULT) { \
83 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
84 WARN("Out of 'bogus' video memory\n"); \
85 HeapFree(GetProcessHeap(),0,object); \
87 return D3DERR_OUTOFVIDEOMEMORY; \
89 globalChangeGlRam(_size); \
91 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
92 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
93 FIXME("Out of memory!\n"); \
94 HeapFree(GetProcessHeap(), 0, object); \
96 return D3DERR_OUTOFVIDEOMEMORY; \
98 *pp##type = (IWineD3D##type *) object; \
99 TRACE("(%p) : Created resource %p\n", This, object); \
102 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
103 _basetexture.levels = Levels; \
104 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
105 _basetexture.LOD = 0; \
106 _basetexture.dirty = TRUE; \
109 /**********************************************************
110 * Global variable / Constants follow
111 **********************************************************/
112 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
114 /**********************************************************
115 * Utility functions follow
116 **********************************************************/
117 /* Convert the D3DLIGHT properties into equivalent gl lights */
118 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
121 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
122 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
124 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
125 glMatrixMode(GL_MODELVIEW);
127 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
130 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
131 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
132 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
133 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
134 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
135 checkGLcall("glLightfv");
138 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
139 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
140 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
141 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
142 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
143 checkGLcall("glLightfv");
146 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
147 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
148 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
149 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
150 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
151 checkGLcall("glLightfv");
153 /* Attenuation - Are these right? guessing... */
154 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
155 checkGLcall("glLightf");
156 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
157 checkGLcall("glLightf");
159 if ((lightInfo->OriginalParms.Range * lightInfo->OriginalParms.Range) != 0 ) {
160 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
162 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
165 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
166 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
167 checkGLcall("glLightf");
169 switch (lightInfo->OriginalParms.Type) {
172 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
173 checkGLcall("glLightfv");
174 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
175 checkGLcall("glLightf");
181 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
182 checkGLcall("glLightfv");
184 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
185 checkGLcall("glLightfv");
186 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
187 checkGLcall("glLightf");
188 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
189 checkGLcall("glLightf");
193 case D3DLIGHT_DIRECTIONAL:
195 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
196 checkGLcall("glLightfv");
197 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
198 checkGLcall("glLightf");
199 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
200 checkGLcall("glLightf");
204 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
207 /* Restore the modelview matrix */
211 /* Apply the current values to the specified texture stage */
212 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
213 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
216 BOOL changeTexture = TRUE;
218 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
219 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
224 /* Performance: For texture states where multiples effect the outcome, only bother
225 applying the last one as it will pick up all the other values */
226 case WINED3DTSS_COLORARG0: /* Will be picked up when setting color op */
227 case WINED3DTSS_COLORARG1: /* Will be picked up when setting color op */
228 case WINED3DTSS_COLORARG2: /* Will be picked up when setting color op */
229 case WINED3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
230 case WINED3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
231 case WINED3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
235 /* Performance: If the texture states only impact settings for the texture unit
236 (compared to the texture object) then there is no need to reapply them. The
237 only time they need applying is the first time, since we cheat and put the
238 values into the stateblock without applying.
239 Per-texture unit: texture function (eg. combine), ops and args
241 texture generation settings
242 Note: Due to some special conditions there may be a need to do particular ones
243 of these, which is what the Flags allows */
244 case WINED3DTSS_COLOROP:
245 case WINED3DTSS_TEXCOORDINDEX:
246 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
249 case WINED3DTSS_ALPHAOP:
250 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
258 /* Performance: Only change to this texture if we have to */
260 /* Make appropriate texture active */
261 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
262 GLACTIVETEXTURE(Stage);
263 } else if (Stage > 0) {
264 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
266 changeTexture = FALSE;
269 /* Now apply the change */
270 IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
274 /* apply the sampler states to the texture */
275 for (i = 1; i <= HIGHEST_SAMPLER_STATE;i++) {
276 IWineD3DDevice_SetSamplerState(iface, Stage, i, This->stateBlock->samplerState[Stage][i]);
279 /* Note the D3DRS value applies to all textures, but GL has one
280 * per texture, so apply it now ready to be used!
282 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
283 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
284 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
286 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
289 /**********************************************************
290 * IUnknown parts follows
291 **********************************************************/
293 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
295 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
296 /* FIXME: This needs to extend an IWineD3DBaseObject */
298 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
299 if (IsEqualGUID(riid, &IID_IUnknown)
300 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
301 IUnknown_AddRef(iface);
306 return E_NOINTERFACE;
309 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
310 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
311 ULONG refCount = InterlockedIncrement(&This->ref);
313 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
317 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
318 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
319 ULONG refCount = InterlockedDecrement(&This->ref);
321 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
324 /* TODO: Clean up all the surfaces and textures! */
325 /* FIXME: Create targets and state blocks in d3d8 */
326 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
327 /* NOTE: You must release the parent if the object was created via a callback
328 ** ***************************/
330 IUnknown* swapChainParent;
332 /* Release all of the swapchains, except the implicit swapchain (#0) */
333 for(i = 1; i < This->numberOfSwapChains; i++) {
334 /* TODO: don't access swapchains[x] directly! */
335 IWineD3DSwapChain_Release(This->swapchains[i]);
338 if (This->stateBlock != NULL) {
339 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
342 if (This->swapchains[0] != NULL) {
343 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release its parent now */
344 /* TODO: don't access swapchains[x] directly!, check that there are no-more swapchains left for this device! */
345 IWineD3DSwapChain_GetParent(This->swapchains[0], &swapChainParent);
346 IUnknown_Release(swapChainParent); /* once for the get parent */
347 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
348 FIXME("(%p) Something's still holding the implicit swapchain\n",This);
353 IWineD3D_Release(This->wineD3D);
354 HeapFree(GetProcessHeap(), 0, This);
359 /**********************************************************
360 * IWineD3DDevice implementation follows
361 **********************************************************/
362 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
363 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
364 *pParent = This->parent;
365 IUnknown_AddRef(This->parent);
369 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
370 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
372 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
373 IWineD3DVertexBufferImpl *object;
374 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
375 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
378 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
379 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
383 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
384 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
389 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
390 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
391 HANDLE *sharedHandle, IUnknown *parent) {
392 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
393 IWineD3DIndexBufferImpl *object;
394 TRACE("(%p) Creating index buffer\n", This);
396 /* Allocate the storage for the device */
397 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
400 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
401 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
404 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
405 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
406 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
411 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
413 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
414 IWineD3DStateBlockImpl *object;
417 D3DCREATEOBJECTINSTANCE(object, StateBlock)
418 object->blockType = Type;
420 /* Special case - Used during initialization to produce a placeholder stateblock
421 so other functions called can update a state block */
422 if (Type == (D3DSTATEBLOCKTYPE) 0) {
423 /* Don't bother increasing the reference count otherwise a device will never
424 be freed due to circular dependencies */
428 /* Otherwise, might as well set the whole state block to the appropriate values */
429 IWineD3DDevice_AddRef(iface);
430 /* Otherwise, might as well set the whole state block to the appropriate values */
431 if ( This->stateBlock != NULL) {
432 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
434 memset(object->streamFreq, 1, sizeof(object->streamFreq));
437 /* Reset the ref and type after kludging it */
438 object->wineD3DDevice = This;
440 object->blockType = Type;
442 TRACE("Updating changed flags appropriate for type %d\n", Type);
444 if (Type == D3DSBT_ALL) {
445 TRACE("ALL => Pretend everything has changed\n");
446 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
447 } else if (Type == D3DSBT_PIXELSTATE) {
449 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
450 /* TODO: Pixel Shader Constants */
451 object->changed.pixelShader = TRUE;
452 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
453 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
455 for (j = 0; j < GL_LIMITS(textures); i++) {
456 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
457 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
460 /* Setting sampler block changes states */
461 for (j = 0 ; j < GL_LIMITS(samplers); j++) {
462 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
464 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
467 } else if (Type == D3DSBT_VERTEXSTATE) {
469 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
471 /* TODO: Vertex Shader Constants */
472 object->changed.vertexShader = TRUE;
473 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
474 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
476 for (j = 0; j < GL_LIMITS(textures); i++) {
477 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
478 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
481 /* Setting sampler block changes states */
482 for (j = 0 ; j < GL_LIMITS(samplers); j++) {
483 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
484 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
488 /* Duplicate light chain */
490 PLIGHTINFOEL *src = NULL;
491 PLIGHTINFOEL *dst = NULL;
492 PLIGHTINFOEL *newEl = NULL;
493 src = This->stateBlock->lights;
494 object->lights = NULL;
498 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
499 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
500 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
502 newEl->changed = TRUE;
503 newEl->enabledChanged = TRUE;
505 object->lights = newEl;
516 FIXME("Unrecognized state block type %d\n", Type);
519 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
524 /* ************************************
526 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
529 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
531 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
533 ******************************** */
535 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
536 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
537 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
538 unsigned int pow2Width, pow2Height;
539 unsigned int Size = 1;
540 TRACE("(%p) Create surface\n",This);
542 /** FIXME: Check ranges on the inputs are valid
545 * [in] Quality level. The valid range is between zero and one less than the level
546 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
547 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
548 * values of paired render targets, depth stencil surfaces, and the MultiSample type
550 *******************************/
555 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
557 * If this flag is set, the contents of the depth stencil buffer will be
558 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
559 * with a different depth surface.
561 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
562 ***************************/
564 if(MultisampleQuality < 0) {
565 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
566 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
569 if(MultisampleQuality > 0) {
570 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
571 MultisampleQuality=0;
574 /* Non-power2 support */
576 /* Find the nearest pow2 match */
577 pow2Width = pow2Height = 1;
578 while (pow2Width < Width) pow2Width <<= 1;
579 while (pow2Height < Height) pow2Height <<= 1;
581 if (pow2Width > Width || pow2Height > Height) {
582 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
583 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
584 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
585 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
586 This, Width, Height);
587 return D3DERR_NOTAVAILABLE;
591 /** TODO: Check against the maximum texture sizes supported by the video card **/
594 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
595 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
597 *********************************/
598 if (Format == WINED3DFMT_DXT1) {
599 /* DXT1 is half byte per pixel */
600 Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4)) >> 1;
602 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
603 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
604 Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4));
606 Size = (Width * D3DFmtGetBpp(This, Format)) * Height;
609 /** Create the and initilise surface resource **/
610 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
611 object->container = (IUnknown*) This;
613 object->currentDesc.Width = Width;
614 object->currentDesc.Height = Height;
615 object->currentDesc.MultiSampleType = MultiSample;
616 object->currentDesc.MultiSampleQuality = MultisampleQuality;
618 /* Setup some glformat defaults */
619 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
620 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
621 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
622 object->glDescription.textureName = 0;
623 object->glDescription.level = Level;
624 object->glDescription.target = GL_TEXTURE_2D;
627 object->pow2Width = pow2Width;
628 object->pow2Height = pow2Height;
629 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
630 object->discard = Discard;
631 object->activeLock = FALSE;
632 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
633 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
635 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
637 /* Precalculated scaling for 'faked' non power of two texture coords */
638 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
639 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
640 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
642 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
644 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
645 * this function is too deap to need to care about things like this.
646 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
647 * ****************************************/
649 case D3DPOOL_SCRATCH:
650 if(Lockable == FALSE)
651 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
652 which are mutually exclusive, setting lockable to true\n");
655 case D3DPOOL_SYSTEMMEM:
656 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
657 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
658 case D3DPOOL_MANAGED:
659 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
660 Usage of DYNAMIC which are mutually exclusive, not doing \
661 anything just telling you.\n");
663 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
664 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
665 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
666 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
669 FIXME("(%p) Unknown pool %d\n", This, Pool);
673 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
674 FIXME("Trying to create a render target that isn't in the default pool\n");
678 object->locked = FALSE;
679 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
681 /* mark the texture as dirty so that it get's loaded first time around*/
682 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
683 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
684 This, Width, Height, Format, debug_d3dformat(Format),
685 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
690 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
691 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
692 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
693 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
695 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
696 IWineD3DTextureImpl *object;
702 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
704 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
705 D3DINITILIZEBASETEXTURE(object->baseTexture);
706 object->width = Width;
707 object->height = Height;
709 /* Calculate levels for mip mapping */
711 TRACE("calculating levels %d\n", object->baseTexture.levels);
712 object->baseTexture.levels++;
715 while (tmpW > 1 && tmpH > 1) {
716 tmpW = max(1, tmpW >> 1);
717 tmpH = max(1, tmpH >> 1);
718 object->baseTexture.levels++;
720 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
723 /* Generate all the surfaces */
726 for (i = 0; i < object->baseTexture.levels; i++)
728 /* use the callback to create the texture surface */
729 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
732 FIXME("Failed to create surface %p \n",object);
734 for(j = 0 ; j < i ; j++) {
735 IWineD3DSurface_Release(object->surfaces[j]);
737 /* heap free object */
738 HeapFree(GetProcessHeap(),0,object);
744 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
745 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
746 /* calculate the next mipmap level */
747 tmpW = max(1, tmpW >> 1);
748 tmpH = max(1, tmpH >> 1);
751 TRACE("(%p) : Created texture %p\n", This, object);
755 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
756 UINT Width, UINT Height, UINT Depth,
757 UINT Levels, DWORD Usage,
758 WINED3DFORMAT Format, D3DPOOL Pool,
759 IWineD3DVolumeTexture** ppVolumeTexture,
760 HANDLE* pSharedHandle, IUnknown *parent,
761 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
763 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
764 IWineD3DVolumeTextureImpl *object;
770 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
771 D3DINITILIZEBASETEXTURE(object->baseTexture);
773 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
774 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
776 object->width = Width;
777 object->height = Height;
778 object->depth = Depth;
780 /* Calculate levels for mip mapping */
782 object->baseTexture.levels++;
786 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
787 tmpW = max(1, tmpW >> 1);
788 tmpH = max(1, tmpH >> 1);
789 tmpD = max(1, tmpD >> 1);
790 object->baseTexture.levels++;
792 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
795 /* Generate all the surfaces */
800 for (i = 0; i < object->baseTexture.levels; i++)
802 /* Create the volume */
803 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
804 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
805 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
807 tmpW = max(1, tmpW >> 1);
808 tmpH = max(1, tmpH >> 1);
809 tmpD = max(1, tmpD >> 1);
812 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
813 TRACE("(%p) : Created volume texture %p\n", This, object);
817 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
818 UINT Width, UINT Height, UINT Depth,
820 WINED3DFORMAT Format, D3DPOOL Pool,
821 IWineD3DVolume** ppVolume,
822 HANDLE* pSharedHandle, IUnknown *parent) {
824 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
825 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
827 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
829 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
830 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
832 object->currentDesc.Width = Width;
833 object->currentDesc.Height = Height;
834 object->currentDesc.Depth = Depth;
835 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
837 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
838 object->lockable = TRUE;
839 object->locked = FALSE;
840 memset(&object->lockedBox, 0, sizeof(D3DBOX));
841 object->dirty = FALSE;
842 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
845 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
846 UINT Levels, DWORD Usage,
847 WINED3DFORMAT Format, D3DPOOL Pool,
848 IWineD3DCubeTexture** ppCubeTexture,
849 HANDLE* pSharedHandle, IUnknown *parent,
850 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
852 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
853 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
858 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
859 D3DINITILIZEBASETEXTURE(object->baseTexture);
861 TRACE("(%p) Create Cube Texture \n", This);
863 object->edgeLength = EdgeLength;
865 /* Calculate levels for mip mapping */
867 object->baseTexture.levels++;
870 tmpW = max(1, tmpW / 2);
871 object->baseTexture.levels++;
873 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
876 /* Generate all the surfaces */
878 for (i = 0; i < object->baseTexture.levels; i++) {
880 /* Create the 6 faces */
881 for (j = 0; j < 6; j++) {
883 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
884 i /* Level */, &object->surfaces[j][i],pSharedHandle);
891 IWineD3DSurface_Release(object->surfaces[j][i]);
895 IWineD3DSurface_Release(object->surfaces[l][j]);
899 FIXME("(%p) Failed to create surface\n",object);
900 HeapFree(GetProcessHeap(),0,object);
901 *ppCubeTexture = NULL;
904 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
905 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
907 tmpW = max(1, tmpW >> 1);
910 TRACE("(%p) : Created Cube Texture %p\n", This, object);
911 *ppCubeTexture = (IWineD3DCubeTexture *) object;
915 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
916 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
917 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
919 if(NULL == ppQuery) {
920 /* Just a check to see if we support this type of query */
921 HRESULT hr = D3DERR_NOTAVAILABLE;
922 /* Lie and say everything is good (we can return ok fake data from a stub) */
924 case WINED3DQUERYTYPE_VCACHE:
925 case WINED3DQUERYTYPE_RESOURCEMANAGER:
926 case WINED3DQUERYTYPE_VERTEXSTATS:
927 case WINED3DQUERYTYPE_EVENT:
928 case WINED3DQUERYTYPE_OCCLUSION:
929 case WINED3DQUERYTYPE_TIMESTAMP:
930 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
931 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
932 case WINED3DQUERYTYPE_PIPELINETIMINGS:
933 case WINED3DQUERYTYPE_INTERFACETIMINGS:
934 case WINED3DQUERYTYPE_VERTEXTIMINGS:
935 case WINED3DQUERYTYPE_PIXELTIMINGS:
936 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
937 case WINED3DQUERYTYPE_CACHEUTILIZATION:
941 FIXME("(%p) Unhandled query type %d\n",This , Type);
943 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
947 D3DCREATEOBJECTINSTANCE(object, Query)
949 object->extendedData = 0;
950 TRACE("(%p) : Created Query %p\n", This, object);
954 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
955 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
957 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
958 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
959 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
962 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
964 XVisualInfo template;
965 GLXContext oldContext;
966 Drawable oldDrawable;
969 TRACE("(%p) : Created Aditional Swap Chain\n", This);
971 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
972 * does a device hold a reference to a swap chain giving them a lifetime of the device
973 * or does the swap chain notify the device of it'd destruction.
974 *******************************/
976 D3DCREATEOBJECTINSTANCE(object, SwapChain)
978 /* Initialize other useful values */
979 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
981 /*********************
982 * Lookup the window Handle and the relating X window handle
983 ********************/
985 /* Setup hwnd we are using, plus which display this equates to */
986 object->win_handle = *(pPresentationParameters->hDeviceWindow);
987 if (!object->win_handle) {
988 object->win_handle = This->createParms.hFocusWindow;
991 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
992 hDc = GetDC(object->win_handle);
993 object->display = get_display(hDc);
994 ReleaseDC(object->win_handle, hDc);
995 TRACE("Using a display of %p %p \n", object->display, hDc);
997 if (NULL == object->display || NULL == hDc) {
998 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
999 return D3DERR_NOTAVAILABLE;
1002 if (object->win == 0) {
1003 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1004 return D3DERR_NOTAVAILABLE;
1007 * Create an opengl context for the display visual
1008 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1009 * use different properties after that point in time. FIXME: How to handle when requested format
1010 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1011 * it chooses is identical to the one already being used!
1012 **********************************/
1014 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1017 /* Create a new context for this swapchain */
1018 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1019 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1020 (or the best possible if none is requested) */
1021 TRACE("Found x visual ID : %ld\n", template.visualid);
1023 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1024 if (NULL == object->visInfo) {
1025 ERR("cannot really get XVisual\n");
1027 return D3DERR_NOTAVAILABLE;
1030 /* Write out some debug info about the visual/s */
1031 TRACE("Using x visual ID : %ld\n", template.visualid);
1032 TRACE(" visual info: %p\n", object->visInfo);
1033 TRACE(" num items : %d\n", num);
1034 for(n = 0;n < num; n++) {
1035 TRACE("=====item=====: %d\n", n + 1);
1036 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1037 TRACE(" screen : %d\n", object->visInfo[n].screen);
1038 TRACE(" depth : %u\n", object->visInfo[n].depth);
1039 TRACE(" class : %d\n", object->visInfo[n].class);
1040 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1041 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1042 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1043 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1044 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1045 /* log some extra glx info */
1046 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1047 TRACE(" gl_aux_buffers : %d\n", value);
1048 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1049 TRACE(" gl_buffer_size : %d\n", value);
1050 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1051 TRACE(" gl_red_size : %d\n", value);
1052 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1053 TRACE(" gl_green_size : %d\n", value);
1054 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1055 TRACE(" gl_blue_size : %d\n", value);
1056 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1057 TRACE(" gl_alpha_size : %d\n", value);
1058 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1059 TRACE(" gl_depth_size : %d\n", value);
1060 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1061 TRACE(" gl_stencil_size : %d\n", value);
1063 /* Now choose a simila visual ID*/
1065 #ifdef USE_CONTEXT_MANAGER
1067 /** TODO: use a context mamager **/
1071 IWineD3DSwapChain *implSwapChain;
1072 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1073 /* The first time around we create the context that is shared with all other swapchains and render targets */
1074 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1075 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1078 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1079 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1080 /* and create a new context with the implicit swapchains context as the shared context */
1081 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1082 IWineD3DSwapChain_Release(implSwapChain);
1087 XFree(object->visInfo);
1088 object->visInfo = NULL;
1090 if (NULL == object->glCtx) {
1091 ERR("cannot create glxContext\n");
1093 return D3DERR_NOTAVAILABLE;
1097 if (object->glCtx == NULL) {
1098 ERR("Error in context creation !\n");
1099 return D3DERR_INVALIDCALL;
1101 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1102 object->win_handle, object->glCtx, object->win, object->visInfo);
1105 /*********************
1106 * Windowed / Fullscreen
1107 *******************/
1110 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1111 * so we should really check to see if their is a fullscreen swapchain already
1112 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1113 **************************************/
1115 if (!*(pPresentationParameters->Windowed)) {
1121 /* Get info on the current display setup */
1122 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1123 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1126 /* Change the display settings */
1127 memset(&devmode, 0, sizeof(DEVMODEW));
1128 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1129 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1130 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1131 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1132 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1133 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1135 /* Make popup window */
1136 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1137 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1138 *(pPresentationParameters->BackBufferWidth),
1139 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1145 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1146 * then the corresponding dimension of the client area of the hDeviceWindow
1147 * (or the focus window, if hDeviceWindow is NULL) is taken.
1148 **********************/
1150 if (*(pPresentationParameters->Windowed) &&
1151 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1152 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1155 GetClientRect(object->win_handle, &Rect);
1157 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1158 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1159 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1161 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1162 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1163 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1167 /*********************
1168 * finish off parameter initialization
1169 *******************/
1171 /* Put the correct figures in the presentation parameters */
1172 TRACE("Coppying accross presentaion paraneters\n");
1173 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1174 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1175 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1176 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1177 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1178 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1179 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1180 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1181 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1182 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1183 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1184 object->presentParms.Flags = *(pPresentationParameters->Flags);
1185 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1186 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1189 /* FIXME: check for any failures */
1190 /*********************
1191 * Create the back, front and stencil buffers
1192 *******************/
1193 TRACE("calling rendertarget CB\n");
1194 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1195 object->presentParms.BackBufferWidth,
1196 object->presentParms.BackBufferHeight,
1197 object->presentParms.BackBufferFormat,
1198 object->presentParms.MultiSampleType,
1199 object->presentParms.MultiSampleQuality,
1200 TRUE /* Lockable */,
1201 &object->frontBuffer,
1202 NULL /* pShared (always null)*/);
1203 if (object->frontBuffer != NULL)
1204 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1205 TRACE("calling rendertarget CB\n");
1206 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1207 object->presentParms.BackBufferWidth,
1208 object->presentParms.BackBufferHeight,
1209 object->presentParms.BackBufferFormat,
1210 object->presentParms.MultiSampleType,
1211 object->presentParms.MultiSampleQuality,
1212 TRUE /* Lockable */,
1213 &object->backBuffer,
1214 NULL /* pShared (always null)*/);
1215 if (object->backBuffer != NULL)
1216 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1218 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1219 if (pPresentationParameters->EnableAutoDepthStencil) {
1220 TRACE("Creating depth stencil buffer\n");
1221 if (This->depthStencilBuffer == NULL ) {
1222 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1223 object->presentParms.BackBufferWidth,
1224 object->presentParms.BackBufferHeight,
1225 object->presentParms.AutoDepthStencilFormat,
1226 object->presentParms.MultiSampleType,
1227 object->presentParms.MultiSampleQuality,
1228 FALSE /* FIXME: Discard */,
1229 &This->depthStencilBuffer,
1230 NULL /* pShared (always null)*/ );
1231 if (This->depthStencilBuffer != NULL)
1232 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1235 /** TODO: A check on width, height and multisample types
1236 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1237 ****************************/
1238 object->wantsDepthStencilBuffer = TRUE;
1240 object->wantsDepthStencilBuffer = FALSE;
1243 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1246 /*********************
1247 * init the default renderTarget management
1248 *******************/
1249 object->drawable = object->win;
1250 object->render_ctx = object->glCtx;
1253 /*********************
1254 * Setup some defaults and clear down the buffers
1255 *******************/
1257 /** save current context and drawable **/
1258 oldContext = glXGetCurrentContext();
1259 oldDrawable = glXGetCurrentDrawable();
1261 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1262 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1263 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1265 checkGLcall("glXMakeCurrent");
1267 TRACE("Setting up the screen\n");
1268 /* Clear the screen */
1269 glClearColor(0.0, 0.0, 0.0, 0.0);
1270 checkGLcall("glClearColor");
1273 glClearStencil(0xffff);
1275 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1276 checkGLcall("glClear");
1278 glColor3f(1.0, 1.0, 1.0);
1279 checkGLcall("glColor3f");
1281 glEnable(GL_LIGHTING);
1282 checkGLcall("glEnable");
1284 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1285 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1287 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1288 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1290 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1291 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1293 /* switch back to the original context (unless it was zero)*/
1294 if (This->numberOfSwapChains != 0) {
1295 /** TODO: restore the context and drawable **/
1296 glXMakeCurrent(object->display, oldDrawable, oldContext);
1301 /* TODO: move this off into a linked list implementation! (add swapchain, remove swapchain or something along those lines) */
1303 IListOperator *listOperator;
1304 IListStore_CreateListOperator(This->swapchainStore, &listOperator);
1305 IListOperator_Append(listOperator, (void *)object);
1306 IListOperator_Release(listOperator);
1309 This->swapchains[This->numberOfSwapChains++] = (IWineD3DSwapChain *)object;
1310 TRACE("Set swapchain to %p\n", object);
1311 } else { /* something went wrong so clean up */
1312 IUnknown* bufferParent;
1313 if (object->frontBuffer) {
1314 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1315 IUnknown_Release(bufferParent); /* once for the get parent */
1316 if(IUnknown_Release(bufferParent) > 0) {
1317 FIXME("(%p) Something's still holding the front buffer\n",This);
1320 if (object->backBuffer) {
1321 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1322 IUnknown_Release(bufferParent); /* once for the get parent */
1323 if(IUnknown_Release(bufferParent) > 0) {
1324 FIXME("(%p) Something's still holding the back buffer\n",This);
1327 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1328 /* Clean up the context */
1329 /* check that we are the current context first (we shouldn't be though!) */
1330 if (object->glCtx != 0) {
1331 if(glXGetCurrentContext() == object->glCtx) {
1332 glXMakeCurrent(object->display, None, NULL);
1334 glXDestroyContext(object->display, object->glCtx);
1336 HeapFree(GetProcessHeap(), 0, object);
1342 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1343 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1346 /* TODO: move over to using a linked list. */
1347 TRACE("(%p) returning %d\n", This, This->numberOfSwapChains);
1348 return This->numberOfSwapChains;
1351 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1352 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1353 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1355 if(iSwapChain >= IWineD3DDeviceImpl_GetNumberOfSwapChains(iface) || iSwapChain < 0) {
1357 return D3DERR_INVALIDCALL;
1359 /** TODO: move off to a linked list implementation **/
1360 *pSwapChain = This->swapchains[iSwapChain];
1363 /* TODO: move over to using stores and linked lists. */
1365 IWineD3DSwapChain_AddRef(*pSwapChain);
1366 TRACE("(%p) returning %p\n", This, *pSwapChain);
1370 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1371 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1373 FIXME("(%p) : Stub\n",This);
1379 * Vertex Declaration
1381 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1382 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1383 IWineD3DVertexDeclarationImpl *object = NULL;
1384 HRESULT hr = D3D_OK;
1385 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1386 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1389 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1394 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1395 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1396 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1397 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1398 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1399 object->function = pFunction;
1400 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1405 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1406 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1407 FIXME("(%p) : Stub\n", This);
1411 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1413 *ppD3D= This->wineD3D;
1414 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1415 IWineD3D_AddRef(*ppD3D);
1420 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1421 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1422 * Into the video ram as possible and seeing how many fit
1423 * you can also get the correct initial value from via X and ATI's driver
1424 *******************/
1425 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1426 static BOOL showfixmes = TRUE;
1428 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1429 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1432 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1433 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1434 /* videomemory is simulated videomemory + AGP memory left */
1435 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1443 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1444 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1446 /* Update the current state block */
1447 This->updateStateBlock->fvf = fvf;
1448 This->updateStateBlock->changed.fvf = TRUE;
1449 This->updateStateBlock->set.fvf = TRUE;
1451 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1452 /* clear down the vertex declaration
1453 NOTE: Axis and Allies doesn't work properly otherwise
1454 (may be a stateblock problem though!)
1456 /* No difference if recording or not */
1457 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1462 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1463 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1464 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1465 *pfvf = This->stateBlock->fvf;
1470 * Get / Set Stream Source
1472 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1473 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1474 IWineD3DVertexBuffer *oldSrc;
1476 oldSrc = This->stateBlock->streamSource[StreamNumber];
1477 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1479 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1480 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1481 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1482 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1483 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1485 /* Handle recording of state blocks */
1486 if (This->isRecordingState) {
1487 TRACE("Recording... not performing anything\n");
1491 /* Not recording... */
1492 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
1493 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
1498 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1499 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1501 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1502 *pStream = This->stateBlock->streamSource[StreamNumber];
1503 *pStride = This->stateBlock->streamStride[StreamNumber];
1504 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1505 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1509 /*Should be quite easy, just an extension of vertexdata
1511 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1513 The divider is a bit odd though
1515 VertexOffset = StartVertex / Divider * StreamStride +
1516 VertexIndex / Divider * StreamStride + StreamOffset
1519 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1520 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1522 FIXME("(%p) : stub\n", This);
1526 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1527 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1529 FIXME("(%p) : stub\n", This);
1534 * Get / Set & Multiply Transform
1536 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1537 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1539 /* Most of this routine, comments included copied from ddraw tree initially: */
1540 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1542 /* Handle recording of state blocks */
1543 if (This->isRecordingState) {
1544 TRACE("Recording... not performing anything\n");
1545 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1546 This->updateStateBlock->set.transform[d3dts] = TRUE;
1547 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1552 * If the new matrix is the same as the current one,
1553 * we cut off any further processing. this seems to be a reasonable
1554 * optimization because as was noticed, some apps (warcraft3 for example)
1555 * tend towards setting the same matrix repeatedly for some reason.
1557 * From here on we assume that the new matrix is different, wherever it matters.
1559 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1560 TRACE("The app is setting the same matrix over again\n");
1563 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1567 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1568 where ViewMat = Camera space, WorldMat = world space.
1570 In OpenGL, camera and world space is combined into GL_MODELVIEW
1571 matrix. The Projection matrix stay projection matrix.
1574 /* Capture the times we can just ignore the change for now */
1575 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1576 This->modelview_valid = FALSE;
1579 } else if (d3dts == D3DTS_PROJECTION) {
1580 This->proj_valid = FALSE;
1583 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1584 /* Indexed Vertex Blending Matrices 256 -> 511 */
1585 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1586 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1590 /* Now we really are going to have to change a matrix */
1593 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1594 if (d3dts < GL_LIMITS(textures)) {
1595 int tex = d3dts - D3DTS_TEXTURE0;
1596 GLACTIVETEXTURE(tex);
1597 set_texture_matrix((float *)lpmatrix,
1598 This->updateStateBlock->textureState[tex][WINED3DTSS_TEXTURETRANSFORMFLAGS]);
1601 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1604 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1605 * NOTE: We have to reset the positions even if the light/plane is not currently
1606 * enabled, since the call to enable it will not reset the position.
1607 * NOTE2: Apparently texture transforms do NOT need reapplying
1610 PLIGHTINFOEL *lightChain = NULL;
1611 This->modelview_valid = FALSE;
1612 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1614 glMatrixMode(GL_MODELVIEW);
1615 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1617 glLoadMatrixf((float *)lpmatrix);
1618 checkGLcall("glLoadMatrixf(...)");
1621 lightChain = This->stateBlock->lights;
1622 while (lightChain && lightChain->glIndex != -1) {
1623 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1624 checkGLcall("glLightfv posn");
1625 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1626 checkGLcall("glLightfv dirn");
1627 lightChain = lightChain->next;
1630 /* Reset Clipping Planes if clipping is enabled */
1631 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1632 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1633 checkGLcall("glClipPlane");
1637 } else { /* What was requested!?? */
1638 WARN("invalid matrix specified: %i\n", d3dts);
1641 /* Release lock, all done */
1646 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1647 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1648 TRACE("(%p) : for Transform State %d\n", This, State);
1649 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1653 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1654 D3DMATRIX *mat = NULL;
1657 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1658 * below means it will be recorded in a state block change, but it
1659 * works regardless where it is recorded.
1660 * If this is found to be wrong, change to StateBlock.
1662 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1663 TRACE("(%p) : For state %u\n", This, State);
1665 if (State < HIGHEST_TRANSFORMSTATE)
1667 mat = &This->updateStateBlock->transforms[State];
1669 FIXME("Unhandled transform state!!\n");
1672 /* Copied from ddraw code: */
1673 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) + (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1674 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) + (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1675 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) + (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1676 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) + (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1678 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) + (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1679 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) + (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1680 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) + (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1681 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) + (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1683 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) + (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1684 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) + (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1685 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) + (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1686 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) + (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1688 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) + (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1689 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) + (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1690 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) + (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1691 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) + (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1693 /* Apply change via set transform - will reapply to eg. lights this way */
1694 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1700 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1702 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1703 you can reference any indexes you want as long as that number max are enabled at any
1704 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1705 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1706 but when recording, just build a chain pretty much of commands to be replayed. */
1708 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1710 PLIGHTINFOEL *object, *temp;
1712 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1713 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1715 /* If recording state block, just add to end of lights chain */
1716 if (This->isRecordingState) {
1717 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1718 if (NULL == object) {
1719 return D3DERR_OUTOFVIDEOMEMORY;
1721 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1722 object->OriginalIndex = Index;
1723 object->glIndex = -1;
1724 object->changed = TRUE;
1726 /* Add to the END of the chain of lights changes to be replayed */
1727 if (This->updateStateBlock->lights == NULL) {
1728 This->updateStateBlock->lights = object;
1730 temp = This->updateStateBlock->lights;
1731 while (temp->next != NULL) temp=temp->next;
1732 temp->next = object;
1734 TRACE("Recording... not performing anything more\n");
1738 /* Ok, not recording any longer so do real work */
1739 object = This->stateBlock->lights;
1740 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1742 /* If we didn't find it in the list of lights, time to add it */
1743 if (object == NULL) {
1744 PLIGHTINFOEL *insertAt,*prevPos;
1746 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1747 if (NULL == object) {
1748 return D3DERR_OUTOFVIDEOMEMORY;
1750 object->OriginalIndex = Index;
1751 object->glIndex = -1;
1753 /* Add it to the front of list with the idea that lights will be changed as needed
1754 BUT after any lights currently assigned GL indexes */
1755 insertAt = This->stateBlock->lights;
1757 while (insertAt != NULL && insertAt->glIndex != -1) {
1759 insertAt = insertAt->next;
1762 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1763 This->stateBlock->lights = object;
1764 } else if (insertAt == NULL) { /* End of list */
1765 prevPos->next = object;
1766 object->prev = prevPos;
1767 } else { /* Middle of chain */
1768 if (prevPos == NULL) {
1769 This->stateBlock->lights = object;
1771 prevPos->next = object;
1773 object->prev = prevPos;
1774 object->next = insertAt;
1775 insertAt->prev = object;
1779 /* Initialze the object */
1780 TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
1781 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1782 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1783 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1784 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1785 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1786 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1788 /* Save away the information */
1789 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1791 switch (pLight->Type) {
1792 case D3DLIGHT_POINT:
1794 object->lightPosn[0] = pLight->Position.x;
1795 object->lightPosn[1] = pLight->Position.y;
1796 object->lightPosn[2] = pLight->Position.z;
1797 object->lightPosn[3] = 1.0f;
1798 object->cutoff = 180.0f;
1802 case D3DLIGHT_DIRECTIONAL:
1804 object->lightPosn[0] = -pLight->Direction.x;
1805 object->lightPosn[1] = -pLight->Direction.y;
1806 object->lightPosn[2] = -pLight->Direction.z;
1807 object->lightPosn[3] = 0.0;
1808 object->exponent = 0.0f;
1809 object->cutoff = 180.0f;
1814 object->lightPosn[0] = pLight->Position.x;
1815 object->lightPosn[1] = pLight->Position.y;
1816 object->lightPosn[2] = pLight->Position.z;
1817 object->lightPosn[3] = 1.0;
1820 object->lightDirn[0] = pLight->Direction.x;
1821 object->lightDirn[1] = pLight->Direction.y;
1822 object->lightDirn[2] = pLight->Direction.z;
1823 object->lightDirn[3] = 1.0;
1826 * opengl-ish and d3d-ish spot lights use too different models for the
1827 * light "intensity" as a function of the angle towards the main light direction,
1828 * so we only can approximate very roughly.
1829 * however spot lights are rather rarely used in games (if ever used at all).
1830 * furthermore if still used, probably nobody pays attention to such details.
1832 if (pLight->Falloff == 0) {
1835 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1837 if (rho < 0.0001) rho = 0.0001f;
1838 object->exponent = -0.3/log(cos(rho/2));
1839 object->cutoff = pLight->Phi*90/M_PI;
1845 FIXME("Unrecognized light type %d\n", pLight->Type);
1848 /* Update the live definitions if the light is currently assigned a glIndex */
1849 if (object->glIndex != -1) {
1850 setup_light(iface, object->glIndex, object);
1855 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1856 PLIGHTINFOEL *lightInfo = NULL;
1857 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1858 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1860 /* Locate the light in the live lights */
1861 lightInfo = This->stateBlock->lights;
1862 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1864 if (lightInfo == NULL) {
1865 TRACE("Light information requested but light not defined\n");
1866 return D3DERR_INVALIDCALL;
1869 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1874 * Get / Set Light Enable
1875 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1877 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1878 PLIGHTINFOEL *lightInfo = NULL;
1879 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1880 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1882 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1883 if (This->isRecordingState) {
1884 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1885 if (NULL == lightInfo) {
1886 return D3DERR_OUTOFVIDEOMEMORY;
1888 lightInfo->OriginalIndex = Index;
1889 lightInfo->glIndex = -1;
1890 lightInfo->enabledChanged = TRUE;
1892 /* Add to the END of the chain of lights changes to be replayed */
1893 if (This->updateStateBlock->lights == NULL) {
1894 This->updateStateBlock->lights = lightInfo;
1896 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1897 while (temp->next != NULL) temp=temp->next;
1898 temp->next = lightInfo;
1900 TRACE("Recording... not performing anything more\n");
1904 /* Not recording... So, locate the light in the live lights */
1905 lightInfo = This->stateBlock->lights;
1906 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1908 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1909 if (lightInfo == NULL) {
1910 D3DLIGHT9 lightParms;
1911 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1912 wait until someone confirms it seems to work! */
1913 TRACE("Light enabled requested but light not defined, so defining one!\n");
1914 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1915 lightParms.Diffuse.r = 1.0;
1916 lightParms.Diffuse.g = 1.0;
1917 lightParms.Diffuse.b = 1.0;
1918 lightParms.Diffuse.a = 0.0;
1919 lightParms.Specular.r = 0.0;
1920 lightParms.Specular.g = 0.0;
1921 lightParms.Specular.b = 0.0;
1922 lightParms.Specular.a = 0.0;
1923 lightParms.Ambient.r = 0.0;
1924 lightParms.Ambient.g = 0.0;
1925 lightParms.Ambient.b = 0.0;
1926 lightParms.Ambient.a = 0.0;
1927 lightParms.Position.x = 0.0;
1928 lightParms.Position.y = 0.0;
1929 lightParms.Position.z = 0.0;
1930 lightParms.Direction.x = 0.0;
1931 lightParms.Direction.y = 0.0;
1932 lightParms.Direction.z = 1.0;
1933 lightParms.Range = 0.0;
1934 lightParms.Falloff = 0.0;
1935 lightParms.Attenuation0 = 0.0;
1936 lightParms.Attenuation1 = 0.0;
1937 lightParms.Attenuation2 = 0.0;
1938 lightParms.Theta = 0.0;
1939 lightParms.Phi = 0.0;
1940 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1942 /* Search for it again! Should be fairly quick as near head of list */
1943 lightInfo = This->stateBlock->lights;
1944 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1945 if (lightInfo == NULL) {
1946 FIXME("Adding default lights has failed dismally\n");
1947 return D3DERR_INVALIDCALL;
1951 /* OK, we now have a light... */
1952 if (Enable == FALSE) {
1954 /* If we are disabling it, check it was enabled, and
1955 still only do something if it has assigned a glIndex (which it should have!) */
1956 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1957 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1959 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1960 checkGLcall("glDisable GL_LIGHT0+Index");
1963 TRACE("Nothing to do as light was not enabled\n");
1965 lightInfo->lightEnabled = FALSE;
1968 /* We are enabling it. If it is enabled, it's really simple */
1969 if (lightInfo->lightEnabled) {
1971 TRACE("Nothing to do as light was enabled\n");
1973 /* If it already has a glIndex, it's still simple */
1974 } else if (lightInfo->glIndex != -1) {
1975 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1976 lightInfo->lightEnabled = TRUE;
1978 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1979 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1982 /* Otherwise got to find space - lights are ordered gl indexes first */
1984 PLIGHTINFOEL *bsf = NULL;
1985 PLIGHTINFOEL *pos = This->stateBlock->lights;
1986 PLIGHTINFOEL *prev = NULL;
1990 /* Try to minimize changes as much as possible */
1991 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1993 /* Try to remember which index can be replaced if necessary */
1994 if (bsf==NULL && pos->lightEnabled == FALSE) {
1995 /* Found a light we can replace, save as best replacement */
1999 /* Step to next space */
2005 /* If we have too many active lights, fail the call */
2006 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2007 FIXME("Program requests too many concurrent lights\n");
2008 return D3DERR_INVALIDCALL;
2010 /* If we have allocated all lights, but not all are enabled,
2011 reuse one which is not enabled */
2012 } else if (Index == This->maxConcurrentLights) {
2013 /* use bsf - Simply swap the new light and the BSF one */
2014 PLIGHTINFOEL *bsfNext = bsf->next;
2015 PLIGHTINFOEL *bsfPrev = bsf->prev;
2018 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2019 if (bsf->prev != NULL) {
2020 bsf->prev->next = lightInfo;
2022 This->stateBlock->lights = lightInfo;
2025 /* If not side by side, lots of chains to update */
2026 if (bsf->next != lightInfo) {
2027 lightInfo->prev->next = bsf;
2028 bsf->next->prev = lightInfo;
2029 bsf->next = lightInfo->next;
2030 bsf->prev = lightInfo->prev;
2031 lightInfo->next = bsfNext;
2032 lightInfo->prev = bsfPrev;
2036 bsf->prev = lightInfo;
2037 bsf->next = lightInfo->next;
2038 lightInfo->next = bsf;
2039 lightInfo->prev = bsfPrev;
2044 glIndex = bsf->glIndex;
2046 lightInfo->glIndex = glIndex;
2047 lightInfo->lightEnabled = TRUE;
2049 /* Finally set up the light in gl itself */
2050 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2052 setup_light(iface, glIndex, lightInfo);
2053 glEnable(GL_LIGHT0 + glIndex);
2054 checkGLcall("glEnable GL_LIGHT0 new setup");
2057 /* If we reached the end of the allocated lights, with space in the
2058 gl lights, setup a new light */
2059 } else if (pos->glIndex == -1) {
2061 /* We reached the end of the allocated gl lights, so already
2062 know the index of the next one! */
2064 lightInfo->glIndex = glIndex;
2065 lightInfo->lightEnabled = TRUE;
2067 /* In an ideal world, it's already in the right place */
2068 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2069 /* No need to move it */
2071 /* Remove this light from the list */
2072 lightInfo->prev->next = lightInfo->next;
2073 if (lightInfo->next != NULL) {
2074 lightInfo->next->prev = lightInfo->prev;
2077 /* Add in at appropriate place (inbetween prev and pos) */
2078 lightInfo->prev = prev;
2079 lightInfo->next = pos;
2081 This->stateBlock->lights = lightInfo;
2083 prev->next = lightInfo;
2086 pos->prev = lightInfo;
2090 /* Finally set up the light in gl itself */
2091 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2093 setup_light(iface, glIndex, lightInfo);
2094 glEnable(GL_LIGHT0 + glIndex);
2095 checkGLcall("glEnable GL_LIGHT0 new setup");
2104 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2106 PLIGHTINFOEL *lightInfo = NULL;
2107 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2108 TRACE("(%p) : for idx(%ld)\n", This, Index);
2110 /* Locate the light in the live lights */
2111 lightInfo = This->stateBlock->lights;
2112 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2114 if (lightInfo == NULL) {
2115 TRACE("Light enabled state requested but light not defined\n");
2116 return D3DERR_INVALIDCALL;
2118 *pEnable = lightInfo->lightEnabled;
2123 * Get / Set Clip Planes
2125 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2126 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2127 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2129 /* Validate Index */
2130 if (Index >= GL_LIMITS(clipplanes)) {
2131 TRACE("Application has requested clipplane this device doesn't support\n");
2132 return D3DERR_INVALIDCALL;
2135 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2136 This->updateStateBlock->set.clipplane[Index] = TRUE;
2137 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2138 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2139 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2140 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2142 /* Handle recording of state blocks */
2143 if (This->isRecordingState) {
2144 TRACE("Recording... not performing anything\n");
2152 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2153 glMatrixMode(GL_MODELVIEW);
2155 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2157 TRACE("Clipplane [%f,%f,%f,%f]\n",
2158 This->updateStateBlock->clipplane[Index][0],
2159 This->updateStateBlock->clipplane[Index][1],
2160 This->updateStateBlock->clipplane[Index][2],
2161 This->updateStateBlock->clipplane[Index][3]);
2162 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2163 checkGLcall("glClipPlane");
2171 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2172 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2173 TRACE("(%p) : for idx %ld\n", This, Index);
2175 /* Validate Index */
2176 if (Index >= GL_LIMITS(clipplanes)) {
2177 TRACE("Application has requested clipplane this device doesn't support\n");
2178 return D3DERR_INVALIDCALL;
2181 pPlane[0] = This->stateBlock->clipplane[Index][0];
2182 pPlane[1] = This->stateBlock->clipplane[Index][1];
2183 pPlane[2] = This->stateBlock->clipplane[Index][2];
2184 pPlane[3] = This->stateBlock->clipplane[Index][3];
2189 * Get / Set Clip Plane Status
2190 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2192 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2193 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2194 FIXME("(%p) : stub\n", This);
2195 if (NULL == pClipStatus) {
2196 return D3DERR_INVALIDCALL;
2198 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2199 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2203 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2205 FIXME("(%p) : stub\n", This);
2206 if (NULL == pClipStatus) {
2207 return D3DERR_INVALIDCALL;
2209 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2210 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2215 * Get / Set Material
2216 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2218 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2219 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2221 This->updateStateBlock->changed.material = TRUE;
2222 This->updateStateBlock->set.material = TRUE;
2223 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2225 /* Handle recording of state blocks */
2226 if (This->isRecordingState) {
2227 TRACE("Recording... not performing anything\n");
2232 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2233 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2234 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2235 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2236 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2238 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2239 checkGLcall("glMaterialfv");
2240 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2241 checkGLcall("glMaterialfv");
2243 /* Only change material color if specular is enabled, otherwise it is set to black */
2244 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2245 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2246 checkGLcall("glMaterialfv");
2248 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2249 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2250 checkGLcall("glMaterialfv");
2252 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2253 checkGLcall("glMaterialfv");
2254 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2255 checkGLcall("glMaterialf");
2261 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2262 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2263 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2264 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2265 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2266 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2267 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2268 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2275 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2276 UINT BaseVertexIndex) {
2277 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2278 IWineD3DIndexBuffer *oldIdxs;
2280 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2281 oldIdxs = This->updateStateBlock->pIndexData;
2283 This->updateStateBlock->changed.indices = TRUE;
2284 This->updateStateBlock->set.indices = TRUE;
2285 This->updateStateBlock->pIndexData = pIndexData;
2286 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2288 /* Handle recording of state blocks */
2289 if (This->isRecordingState) {
2290 TRACE("Recording... not performing anything\n");
2294 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
2295 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
2299 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2300 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2302 *ppIndexData = This->stateBlock->pIndexData;
2304 /* up ref count on ppindexdata */
2305 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2306 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2312 * Get / Set Viewports
2314 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2315 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2317 TRACE("(%p)\n", This);
2318 This->updateStateBlock->changed.viewport = TRUE;
2319 This->updateStateBlock->set.viewport = TRUE;
2320 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2322 /* Handle recording of state blocks */
2323 if (This->isRecordingState) {
2324 TRACE("Recording... not performing anything\n");
2330 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2331 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2333 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2334 checkGLcall("glDepthRange");
2335 /* Note: GL requires lower left, DirectX supplies upper left */
2336 /* TODO: replace usage of renderTarget with context management */
2337 glViewport(pViewport->X,
2338 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2339 pViewport->Width, pViewport->Height);
2341 checkGLcall("glViewport");
2349 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2350 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2351 TRACE("(%p)\n", This);
2352 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2357 * Get / Set Render States
2358 * TODO: Verify against dx9 definitions
2360 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2363 DWORD OldValue = This->stateBlock->renderState[State];
2365 /* Simple way of referring to either a DWORD or a 4 byte float */
2371 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2372 This->updateStateBlock->changed.renderState[State] = TRUE;
2373 This->updateStateBlock->set.renderState[State] = TRUE;
2374 This->updateStateBlock->renderState[State] = Value;
2376 /* Handle recording of state blocks */
2377 if (This->isRecordingState) {
2378 TRACE("Recording... not performing anything\n");
2385 case WINED3DRS_FILLMODE :
2386 switch ((D3DFILLMODE) Value) {
2387 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2388 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2389 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2391 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2393 checkGLcall("glPolygonMode (fillmode)");
2396 case WINED3DRS_LIGHTING :
2398 glEnable(GL_LIGHTING);
2399 checkGLcall("glEnable GL_LIGHTING");
2401 glDisable(GL_LIGHTING);
2402 checkGLcall("glDisable GL_LIGHTING");
2406 case WINED3DRS_ZENABLE :
2407 switch ((D3DZBUFFERTYPE) Value) {
2409 glDisable(GL_DEPTH_TEST);
2410 checkGLcall("glDisable GL_DEPTH_TEST");
2413 glEnable(GL_DEPTH_TEST);
2414 checkGLcall("glEnable GL_DEPTH_TEST");
2417 glEnable(GL_DEPTH_TEST);
2418 checkGLcall("glEnable GL_DEPTH_TEST");
2419 FIXME("W buffer is not well handled\n");
2422 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2426 case WINED3DRS_CULLMODE :
2428 /* If we are culling "back faces with clockwise vertices" then
2429 set front faces to be counter clockwise and enable culling
2431 switch ((D3DCULL) Value) {
2433 glDisable(GL_CULL_FACE);
2434 checkGLcall("glDisable GL_CULL_FACE");
2437 glEnable(GL_CULL_FACE);
2438 checkGLcall("glEnable GL_CULL_FACE");
2439 if (This->renderUpsideDown) {
2441 checkGLcall("glFrontFace GL_CW");
2443 glFrontFace(GL_CCW);
2444 checkGLcall("glFrontFace GL_CCW");
2446 glCullFace(GL_BACK);
2449 glEnable(GL_CULL_FACE);
2450 checkGLcall("glEnable GL_CULL_FACE");
2451 if (This->renderUpsideDown) {
2452 glFrontFace(GL_CCW);
2453 checkGLcall("glFrontFace GL_CCW");
2456 checkGLcall("glFrontFace GL_CW");
2458 glCullFace(GL_BACK);
2461 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2465 case WINED3DRS_SHADEMODE :
2466 switch ((D3DSHADEMODE) Value) {
2468 glShadeModel(GL_FLAT);
2469 checkGLcall("glShadeModel");
2471 case D3DSHADE_GOURAUD:
2472 glShadeModel(GL_SMOOTH);
2473 checkGLcall("glShadeModel");
2475 case D3DSHADE_PHONG:
2476 FIXME("D3DSHADE_PHONG isn't supported?\n");
2479 return D3DERR_INVALIDCALL;
2481 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2485 case WINED3DRS_DITHERENABLE :
2487 glEnable(GL_DITHER);
2488 checkGLcall("glEnable GL_DITHER");
2490 glDisable(GL_DITHER);
2491 checkGLcall("glDisable GL_DITHER");
2495 case WINED3DRS_ZWRITEENABLE :
2498 checkGLcall("glDepthMask");
2501 checkGLcall("glDepthMask");
2505 case WINED3DRS_ZFUNC :
2507 int glParm = GL_LESS;
2509 switch ((D3DCMPFUNC) Value) {
2510 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2511 case D3DCMP_LESS: glParm=GL_LESS; break;
2512 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2513 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2514 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2515 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2516 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2517 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2519 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2521 glDepthFunc(glParm);
2522 checkGLcall("glDepthFunc");
2526 case WINED3DRS_AMBIENT :
2529 D3DCOLORTOGLFLOAT4(Value, col);
2530 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2531 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2532 checkGLcall("glLightModel for MODEL_AMBIENT");
2537 case WINED3DRS_ALPHABLENDENABLE :
2540 checkGLcall("glEnable GL_BLEND");
2542 glDisable(GL_BLEND);
2543 checkGLcall("glDisable GL_BLEND");
2547 case WINED3DRS_SRCBLEND :
2548 case WINED3DRS_DESTBLEND :
2550 int newVal = GL_ZERO;
2552 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2553 case D3DBLEND_ONE : newVal = GL_ONE; break;
2554 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2555 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2556 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2557 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2558 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2559 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2560 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2561 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2562 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2564 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2565 This->srcBlend = newVal;
2566 This->dstBlend = newVal;
2569 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2570 This->srcBlend = newVal;
2571 This->dstBlend = newVal;
2574 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2577 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2578 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2579 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2580 glBlendFunc(This->srcBlend, This->dstBlend);
2582 checkGLcall("glBlendFunc");
2586 case WINED3DRS_ALPHATESTENABLE :
2588 glEnable(GL_ALPHA_TEST);
2589 checkGLcall("glEnable GL_ALPHA_TEST");
2591 glDisable(GL_ALPHA_TEST);
2592 checkGLcall("glDisable GL_ALPHA_TEST");
2596 case WINED3DRS_ALPHAFUNC :
2598 int glParm = GL_LESS;
2599 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2601 switch ((D3DCMPFUNC) Value) {
2602 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2603 case D3DCMP_LESS: glParm = GL_LESS; break;
2604 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2605 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2606 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2607 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2608 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2609 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2611 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2613 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2614 glAlphaFunc(glParm, ref);
2615 This->alphafunc = glParm;
2616 checkGLcall("glAlphaFunc");
2620 case WINED3DRS_ALPHAREF :
2622 int glParm = This->alphafunc;
2625 ref = ((float) Value) / 255.0f;
2626 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2627 glAlphaFunc(glParm, ref);
2628 checkGLcall("glAlphaFunc");
2632 case WINED3DRS_CLIPPLANEENABLE :
2633 case WINED3DRS_CLIPPING :
2635 /* Ensure we only do the changed clip planes */
2636 DWORD enable = 0xFFFFFFFF;
2637 DWORD disable = 0x00000000;
2639 /* If enabling / disabling all */
2640 if (State == WINED3DRS_CLIPPING) {
2642 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2645 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2649 enable = Value & ~OldValue;
2650 disable = ~Value & OldValue;
2653 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2654 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2655 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2656 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2657 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2658 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2660 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2661 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2662 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2663 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2664 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2665 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2667 /** update clipping status */
2669 This->stateBlock->clip_status.ClipUnion = 0;
2670 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2672 This->stateBlock->clip_status.ClipUnion = 0;
2673 This->stateBlock->clip_status.ClipIntersection = 0;
2678 case WINED3DRS_BLENDOP :
2680 int glParm = GL_FUNC_ADD;
2682 switch ((D3DBLENDOP) Value) {
2683 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2684 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2685 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2686 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2687 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2689 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2691 TRACE("glBlendEquation(%x)\n", glParm);
2692 glBlendEquation(glParm);
2693 checkGLcall("glBlendEquation");
2697 case WINED3DRS_TEXTUREFACTOR :
2701 /* Note the texture color applies to all textures whereas
2702 GL_TEXTURE_ENV_COLOR applies to active only */
2704 D3DCOLORTOGLFLOAT4(Value, col);
2705 /* Set the default alpha blend color */
2706 glBlendColor(col[0], col[1], col[2], col[3]);
2707 checkGLcall("glBlendColor");
2709 /* And now the default texture color as well */
2710 for (i = 0; i < GL_LIMITS(textures); i++) {
2712 /* Note the D3DRS value applies to all textures, but GL has one
2713 per texture, so apply it now ready to be used! */
2714 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2717 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2720 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2721 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2726 case WINED3DRS_SPECULARENABLE :
2728 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2729 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2730 specular color. This is wrong:
2731 Separate specular color means the specular colour is maintained separately, whereas
2732 single color means it is merged in. However in both cases they are being used to
2734 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2735 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2739 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2740 checkGLcall("glMaterialfv");
2741 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2742 glEnable(GL_COLOR_SUM_EXT);
2744 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2746 checkGLcall("glEnable(GL_COLOR_SUM)");
2748 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2750 /* for the case of enabled lighting: */
2751 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2752 checkGLcall("glMaterialfv");
2754 /* for the case of disabled lighting: */
2755 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2756 glDisable(GL_COLOR_SUM_EXT);
2758 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2760 checkGLcall("glDisable(GL_COLOR_SUM)");
2765 case WINED3DRS_STENCILENABLE :
2767 glEnable(GL_STENCIL_TEST);
2768 checkGLcall("glEnable GL_STENCIL_TEST");
2770 glDisable(GL_STENCIL_TEST);
2771 checkGLcall("glDisable GL_STENCIL_TEST");
2775 case WINED3DRS_STENCILFUNC :
2777 int glParm = GL_ALWAYS;
2778 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2779 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2781 switch ((D3DCMPFUNC) Value) {
2782 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2783 case D3DCMP_LESS: glParm=GL_LESS; break;
2784 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2785 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2786 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2787 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2788 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2789 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2791 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2793 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2794 This->stencilfunc = glParm;
2795 glStencilFunc(glParm, ref, mask);
2796 checkGLcall("glStencilFunc");
2800 case WINED3DRS_STENCILREF :
2802 int glParm = This->stencilfunc;
2804 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2807 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2808 glStencilFunc(glParm, ref, mask);
2809 checkGLcall("glStencilFunc");
2813 case WINED3DRS_STENCILMASK :
2815 int glParm = This->stencilfunc;
2816 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2817 GLuint mask = Value;
2819 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2820 glStencilFunc(glParm, ref, mask);
2821 checkGLcall("glStencilFunc");
2825 case WINED3DRS_STENCILFAIL :
2831 fail = StencilOp(Value);
2832 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2833 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2834 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2835 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2837 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2838 glStencilOp(fail, zfail, zpass);
2839 checkGLcall("glStencilOp(fail, zfail, zpass);");
2842 case WINED3DRS_STENCILZFAIL :
2848 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2849 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2850 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2851 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2852 zfail = StencilOp(Value);
2854 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2855 glStencilOp(fail, zfail, zpass);
2856 checkGLcall("glStencilOp(fail, zfail, zpass);");
2859 case WINED3DRS_STENCILPASS :
2865 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2866 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2867 zpass = StencilOp(Value);
2868 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2869 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2871 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2872 glStencilOp(fail, zfail, zpass);
2873 checkGLcall("glStencilOp(fail, zfail, zpass);");
2877 case WINED3DRS_STENCILWRITEMASK :
2879 glStencilMask(Value);
2880 TRACE("glStencilMask(%lu)\n", Value);
2881 checkGLcall("glStencilMask");
2885 case WINED3DRS_FOGENABLE :
2887 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2889 checkGLcall("glEnable GL_FOG");
2892 checkGLcall("glDisable GL_FOG");
2897 case WINED3DRS_RANGEFOGENABLE :
2900 TRACE("Enabled RANGEFOG");
2902 TRACE("Disabled RANGEFOG");
2907 case WINED3DRS_FOGCOLOR :
2910 D3DCOLORTOGLFLOAT4(Value, col);
2911 /* Set the default alpha blend color */
2912 glFogfv(GL_FOG_COLOR, &col[0]);
2913 checkGLcall("glFog GL_FOG_COLOR");
2917 case WINED3DRS_FOGTABLEMODE :
2919 glHint(GL_FOG_HINT, GL_NICEST);
2921 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2922 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2923 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2924 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2926 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2928 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2929 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2934 case WINED3DRS_FOGVERTEXMODE :
2936 glHint(GL_FOG_HINT, GL_FASTEST);
2938 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2939 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2940 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2941 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2943 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2945 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2946 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2951 case WINED3DRS_FOGSTART :
2954 glFogfv(GL_FOG_START, &tmpvalue.f);
2955 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2956 TRACE("Fog Start == %f\n", tmpvalue.f);
2960 case WINED3DRS_FOGEND :
2963 glFogfv(GL_FOG_END, &tmpvalue.f);
2964 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2965 TRACE("Fog End == %f\n", tmpvalue.f);
2969 case WINED3DRS_FOGDENSITY :
2972 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2973 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2977 case WINED3DRS_VERTEXBLEND :
2979 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2980 TRACE("Vertex Blending state to %ld\n", Value);
2984 case WINED3DRS_TWEENFACTOR :
2987 This->updateStateBlock->tween_factor = tmpvalue.f;
2988 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2992 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
2994 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2998 case WINED3DRS_COLORVERTEX :
2999 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3000 case WINED3DRS_SPECULARMATERIALSOURCE :
3001 case WINED3DRS_AMBIENTMATERIALSOURCE :
3002 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3004 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3006 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3007 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3008 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3009 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3010 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3011 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3013 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3014 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3015 Parm = GL_AMBIENT_AND_DIFFUSE;
3019 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3021 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3023 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3030 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3032 This->tracking_color = NEEDS_TRACKING;
3033 This->tracking_parm = Parm;
3037 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3042 case WINED3DRS_LINEPATTERN :
3048 tmppattern.d = Value;
3050 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3052 if (tmppattern.lp.wRepeatFactor) {
3053 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3054 checkGLcall("glLineStipple(repeat, linepattern)");
3055 glEnable(GL_LINE_STIPPLE);
3056 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3058 glDisable(GL_LINE_STIPPLE);
3059 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3064 case WINED3DRS_ZBIAS :
3068 TRACE("ZBias value %f\n", tmpvalue.f);
3069 glPolygonOffset(0, -tmpvalue.f);
3070 checkGLcall("glPolygonOffset(0, -Value)");
3071 glEnable(GL_POLYGON_OFFSET_FILL);
3072 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3073 glEnable(GL_POLYGON_OFFSET_LINE);
3074 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3075 glEnable(GL_POLYGON_OFFSET_POINT);
3076 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3078 glDisable(GL_POLYGON_OFFSET_FILL);
3079 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3080 glDisable(GL_POLYGON_OFFSET_LINE);
3081 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3082 glDisable(GL_POLYGON_OFFSET_POINT);
3083 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3088 case WINED3DRS_NORMALIZENORMALS :
3090 glEnable(GL_NORMALIZE);
3091 checkGLcall("glEnable(GL_NORMALIZE);");
3093 glDisable(GL_NORMALIZE);
3094 checkGLcall("glDisable(GL_NORMALIZE);");
3098 case WINED3DRS_POINTSIZE :
3100 TRACE("Set point size to %f\n", tmpvalue.f);
3101 glPointSize(tmpvalue.f);
3102 checkGLcall("glPointSize(...);");
3105 case WINED3DRS_POINTSIZE_MIN :
3106 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3108 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3109 checkGLcall("glPointParameterfEXT(...);");
3111 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3115 case WINED3DRS_POINTSIZE_MAX :
3116 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3118 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3119 checkGLcall("glPointParameterfEXT(...);");
3121 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3125 case WINED3DRS_POINTSCALE_A :
3126 case WINED3DRS_POINTSCALE_B :
3127 case WINED3DRS_POINTSCALE_C :
3128 case WINED3DRS_POINTSCALEENABLE :
3130 /* If enabled, supply the parameters, otherwise fall back to defaults */
3131 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3132 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3133 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3134 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3135 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3137 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3138 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3139 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3141 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3144 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3145 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3146 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3147 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3149 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3155 case WINED3DRS_COLORWRITEENABLE :
3157 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3158 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3159 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3160 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3161 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3162 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3163 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3164 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3165 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3166 checkGLcall("glColorMask(...)");
3170 case WINED3DRS_LOCALVIEWER :
3172 GLint state = (Value) ? 1 : 0;
3173 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3174 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3178 case WINED3DRS_LASTPIXEL :
3181 TRACE("Last Pixel Drawing Enabled\n");
3183 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3188 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3191 TRACE("Software Processing Enabled\n");
3193 TRACE("Software Processing Disabled\n");
3198 /** not supported */
3199 case WINED3DRS_ZVISIBLE :
3202 return D3DERR_INVALIDCALL;
3205 /* Unhandled yet...! */
3206 case WINED3DRS_EDGEANTIALIAS :
3207 case WINED3DRS_WRAP0 :
3208 case WINED3DRS_WRAP1 :
3209 case WINED3DRS_WRAP2 :
3210 case WINED3DRS_WRAP3 :
3211 case WINED3DRS_WRAP4 :
3212 case WINED3DRS_WRAP5 :
3213 case WINED3DRS_WRAP6 :
3214 case WINED3DRS_WRAP7 :
3215 case WINED3DRS_POINTSPRITEENABLE :
3216 case WINED3DRS_MULTISAMPLEANTIALIAS :
3217 case WINED3DRS_MULTISAMPLEMASK :
3218 case WINED3DRS_PATCHEDGESTYLE :
3219 case WINED3DRS_PATCHSEGMENTS :
3220 case WINED3DRS_DEBUGMONITORTOKEN :
3221 case WINED3DRS_POSITIONORDER :
3222 case WINED3DRS_NORMALORDER :
3223 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3224 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3227 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3235 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3236 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3237 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3238 *pValue = This->stateBlock->renderState[State];
3242 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3243 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3245 * SetSampler is designed to allow for more than the standard up to 8 textures
3246 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3247 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3249 * http://developer.nvidia.com/object/General_FAQ.html#t6
3251 * There are two new settings for GForce
3253 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3254 * and the texture one:
3255 * GL_MAX_TEXTURE_COORDS_ARB.
3256 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3263 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3265 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > HIGHEST_SAMPLER_STATE || Type < 0) {
3266 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), HIGHEST_SAMPLER_STATE, Sampler, Type);
3267 return D3DERR_INVALIDCALL;
3270 This->updateStateBlock->changed.samplerState[Sampler][Type] = TRUE;
3271 This->updateStateBlock->set.samplerState[Sampler][Type] = TRUE;
3272 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3273 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3275 /* Handle recording of state blocks */
3276 if (This->isRecordingState) {
3277 TRACE("Recording... not performing anything\n");
3281 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
3282 clamping, MIPLOD, etc. This will work for up to 16 samplers.
3283 is this just GL_TEXTURE_2D or is it GL_TEXTURE_1D and GL_TEXTURE_3D as well?
3286 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
3287 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3288 GLACTIVETEXTURE(Sampler);
3289 } else if (Sampler > 0) {
3290 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3296 case WINED3DSAMP_ADDRESSU : /* 1 */
3297 case WINED3DSAMP_ADDRESSV : /* 2 */
3298 case WINED3DSAMP_ADDRESSW : /* 3 */
3300 GLint wrapParm = GL_REPEAT;
3302 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3303 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3304 case D3DTADDRESS_BORDER:
3306 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3307 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3309 /* FIXME: Not right, but better */
3310 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3311 wrapParm = GL_REPEAT;
3315 case D3DTADDRESS_MIRROR:
3317 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3318 wrapParm = GL_MIRRORED_REPEAT_ARB;
3320 /* Unsupported in OpenGL pre-1.4 */
3321 TRACE("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3322 wrapParm = GL_REPEAT;
3326 case D3DTADDRESS_MIRRORONCE:
3328 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3329 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3331 TRACE("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3332 wrapParm = GL_REPEAT;
3338 /* This is for the whole context, not just the sampler,
3339 so we should warn if two states are baing set for any given scene */
3341 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3342 wrapParm = GL_REPEAT;
3345 case WINED3DSAMP_ADDRESSU:
3346 TRACE("Setting WRAP_S for %ld to %d \n", Sampler, wrapParm);
3347 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_S, wrapParm);
3348 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3350 case WINED3DSAMP_ADDRESSV:
3351 TRACE("Setting WRAP_T for %ld to %d\n", Sampler, wrapParm);
3352 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_T, wrapParm);
3353 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3356 case WINED3DSAMP_ADDRESSW:
3357 TRACE("Setting WRAP_R for %ld to %d\n", Sampler, wrapParm);
3358 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_R, wrapParm);
3359 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3362 break; /** stupic compilator */
3367 case WINED3DSAMP_BORDERCOLOR : /* 4 */
3370 D3DCOLORTOGLFLOAT4(Value, col);
3371 TRACE("Setting border color for %ld to %lx\n", Sampler, Value);
3372 glTexParameterfv(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_BORDER_COLOR, &col[0]);
3373 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3377 case WINED3DSAMP_MAGFILTER : /* 5 */
3379 DWORD ValueMAG = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAGFILTER];
3380 GLint realVal = GL_NEAREST;
3382 if (ValueMAG == D3DTEXF_POINT) {
3383 realVal = GL_NEAREST;
3384 } else if (ValueMAG == D3DTEXF_LINEAR) {
3385 realVal = GL_LINEAR;
3386 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3387 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3388 realVal = GL_LINEAR;
3390 FIXME("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3391 realVal = GL_NEAREST;
3394 FIXME("Unhandled WINED3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3395 realVal = GL_NEAREST;
3397 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3398 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAG_FILTER, realVal);
3399 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3401 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3403 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3404 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3405 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3406 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3407 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3412 case WINED3DSAMP_MINFILTER: /* 6 */
3413 case WINED3DSAMP_MIPFILTER: /* 7 */
3415 DWORD ValueMIN = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MINFILTER];
3416 DWORD ValueMIP = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPFILTER];
3417 GLint realVal = GL_LINEAR;
3419 if (ValueMIN == D3DTEXF_NONE) {
3420 /* Doesn't really make sense - Windows just seems to disable
3421 mipmapping when this occurs */
3422 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3423 realVal = GL_LINEAR;
3424 } else if (ValueMIN == D3DTEXF_POINT) {
3426 if (ValueMIP == D3DTEXF_NONE) {
3427 realVal = GL_NEAREST;
3428 } else if (ValueMIP == D3DTEXF_POINT) {
3429 realVal = GL_NEAREST_MIPMAP_NEAREST;
3430 } else if (ValueMIP == D3DTEXF_LINEAR) {
3431 realVal = GL_NEAREST_MIPMAP_LINEAR;
3433 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3434 realVal = GL_NEAREST;
3436 } else if (ValueMIN == D3DTEXF_LINEAR) {
3438 if (ValueMIP == D3DTEXF_NONE) {
3439 realVal = GL_LINEAR;
3440 } else if (ValueMIP == D3DTEXF_POINT) {
3441 realVal = GL_LINEAR_MIPMAP_NEAREST;
3442 } else if (ValueMIP == D3DTEXF_LINEAR) {
3443 realVal = GL_LINEAR_MIPMAP_LINEAR;
3445 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3446 realVal = GL_LINEAR;
3448 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3449 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3450 if (ValueMIP == D3DTEXF_NONE) {
3451 realVal = GL_LINEAR_MIPMAP_LINEAR;
3452 } else if (ValueMIP == D3DTEXF_POINT) {
3453 realVal = GL_LINEAR_MIPMAP_NEAREST;
3454 } else if (ValueMIP == D3DTEXF_LINEAR) {
3455 realVal = GL_LINEAR_MIPMAP_LINEAR;
3457 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3458 realVal = GL_LINEAR;
3461 WARN("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3462 realVal = GL_LINEAR;
3465 FIXME("Unhandled WINED3DTSS_MINFILTER value of %ld\n", ValueMIN);
3466 realVal = GL_LINEAR_MIPMAP_LINEAR;
3469 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3470 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MIN_FILTER, realVal);
3471 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3473 * if we just choose to use ANISOTROPIC filtering, refresh openGL state
3475 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3476 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAX_ANISOTROPY_EXT,
3477 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3478 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3483 case WINED3DSAMP_MIPMAPLODBIAS : /* 8 */
3485 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3487 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3488 GL_TEXTURE_LOD_BIAS_EXT,
3490 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3495 case WINED3DSAMP_MAXMIPLEVEL : /* 9 */
3498 * Not really the same, but the more apprioprate than nothing
3500 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3501 GL_TEXTURE_BASE_LEVEL,
3502 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXMIPLEVEL]);
3503 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3507 case WINED3DSAMP_MAXANISOTROPY : /* 10 */
3509 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3510 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3511 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3512 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3513 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3517 case WINED3DSAMP_SRGBTEXTURE : /* 11 */
3518 /* Per texture gamma correction, default 0 */
3519 case WINED3DSAMP_ELEMENTINDEX : /* 12 */
3520 /* When a multi-element textures is used this indicates the element, (what's a multielement texture?) */
3521 case WINED3DSAMP_DMAPOFFSET : /* 13 */
3522 /* Value of a precompiled displacement map used by the tesselator, default 0 */
3523 TRACE("Unsupported sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3527 TRACE("invalid sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3533 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3534 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3535 /** TODO: check that sampler is in range **/
3536 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3537 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3542 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3543 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3546 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3547 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3548 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3553 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3554 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3555 GLint scissorBox[4];
3558 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3559 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3560 pRect->left = scissorBox[1];
3561 pRect->top = scissorBox[2];
3562 pRect->right = scissorBox[1] + scissorBox[3];
3563 pRect->bottom = scissorBox[2] + scissorBox[4];
3564 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3569 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3570 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3572 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3574 /* TODO: what about recording stateblocks? */
3575 if (NULL != pDecl) {
3576 IWineD3DVertexDeclaration_AddRef(pDecl);
3578 if (NULL != This->updateStateBlock->vertexDecl) {
3579 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3581 This->updateStateBlock->vertexDecl = pDecl;
3582 This->updateStateBlock->changed.vertexDecl = TRUE;
3583 This->updateStateBlock->set.vertexDecl = TRUE;
3587 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3590 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3592 *ppDecl = This->updateStateBlock->vertexDecl;
3593 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3597 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3598 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3600 static BOOL showFixmes = TRUE;
3602 This->updateStateBlock->vertexShader = pShader;
3603 This->updateStateBlock->changed.vertexShader = TRUE;
3604 This->updateStateBlock->set.vertexShader = TRUE;
3606 if(pShader == NULL) {
3607 /* clear down the shader */
3608 TRACE("Clear down the shader\n");
3611 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3618 /** FIXME: refernece counting? **/
3619 if (pShader == NULL) { /* only valid with non FVF shaders */
3620 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3621 This->updateStateBlock->vertexShader = NULL;
3623 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3624 This->updateStateBlock->vertexShader = pShader;
3627 This->updateStateBlock->changed.vertexShader = TRUE;
3628 This->updateStateBlock->set.vertexShader = TRUE;
3630 /* Handle recording of state blocks */
3631 if (This->isRecordingState) {
3632 TRACE("Recording... not performing anything\n");
3636 * TODO: merge HAL shaders context switching from prototype
3642 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3644 *ppShader = This->stateBlock->vertexShader;
3645 if(*ppShader != NULL)
3646 IWineD3DVertexShader_AddRef(*ppShader);
3647 TRACE("(%p) : returning %p\n", This, *ppShader);
3651 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3652 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3654 TRACE("(%p) : stub\n", This);
3658 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3659 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3660 TRACE("(%p) : stub\n", This);
3664 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3665 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3666 TRACE("(%p) : stub\n", This);
3670 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3671 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3672 TRACE("(%p) : stub\n", This);
3676 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3677 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3678 TRACE("(%p) : stub\n", This);
3682 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3683 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3684 TRACE("(%p) : stub\n", This);
3688 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3689 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3690 TRACE("(%p) : stub\n", This);
3694 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3695 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3696 TRACE("(%p) : stub\n", This);
3701 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3703 TRACE("(%p) : stub\n", This);
3707 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3708 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3709 TRACE("(%p) : stub\n", This);
3713 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3714 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3715 TRACE("(%p) : stub\n", This);
3719 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3720 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3721 TRACE("(%p) : stub\n", This);
3725 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3726 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3727 TRACE("(%p) : stub\n", This);
3731 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3733 TRACE("(%p) : stub\n", This);
3737 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3739 FIXME("(%p) : stub\n", This);
3744 * Get / Set Texture Stage States
3745 * TODO: Verify against dx9 definitions
3747 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3748 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3750 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3752 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3754 /* Reject invalid texture units */
3755 if (Stage >= GL_LIMITS(textures)) {
3756 TRACE("Attempt to access invalid texture rejected\n");
3757 return D3DERR_INVALIDCALL;
3760 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3761 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3762 This->updateStateBlock->textureState[Stage][Type] = Value;
3764 /* Handle recording of state blocks */
3765 if (This->isRecordingState) {
3766 TRACE("Recording... not performing anything\n");
3772 /* Make appropriate texture active */
3773 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3774 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3775 GLACTIVETEXTURE(Stage);
3776 } else if (Stage > 0) {
3777 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3781 case WINED3DTSS_ALPHAOP :
3782 case WINED3DTSS_COLOROP :
3785 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3786 /* TODO: Disable by making this and all later levels disabled */
3787 glDisable(GL_TEXTURE_1D);
3788 checkGLcall("Disable GL_TEXTURE_1D");
3789 glDisable(GL_TEXTURE_2D);
3790 checkGLcall("Disable GL_TEXTURE_2D");
3791 glDisable(GL_TEXTURE_3D);
3792 checkGLcall("Disable GL_TEXTURE_3D");
3793 break; /* Don't bother setting the texture operations */
3795 /* Enable only the appropriate texture dimension */
3796 if (Type == WINED3DTSS_COLOROP) {
3797 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3798 glEnable(GL_TEXTURE_1D);
3799 checkGLcall("Enable GL_TEXTURE_1D");
3801 glDisable(GL_TEXTURE_1D);
3802 checkGLcall("Disable GL_TEXTURE_1D");
3804 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3805 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3806 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3807 checkGLcall("Enable GL_TEXTURE_2D");
3809 glEnable(GL_TEXTURE_2D);
3810 checkGLcall("Enable GL_TEXTURE_2D");
3813 glDisable(GL_TEXTURE_2D);
3814 checkGLcall("Disable GL_TEXTURE_2D");
3816 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3817 glEnable(GL_TEXTURE_3D);
3818 checkGLcall("Enable GL_TEXTURE_3D");
3820 glDisable(GL_TEXTURE_3D);
3821 checkGLcall("Disable GL_TEXTURE_3D");
3823 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3824 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3825 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3827 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3828 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3832 /* Drop through... (Except disable case) */
3833 case WINED3DTSS_COLORARG0 :
3834 case WINED3DTSS_COLORARG1 :
3835 case WINED3DTSS_COLORARG2 :
3836 case WINED3DTSS_ALPHAARG0 :
3837 case WINED3DTSS_ALPHAARG1 :
3838 case WINED3DTSS_ALPHAARG2 :
3840 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3841 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3843 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3844 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3845 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3846 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3848 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3849 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3850 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3851 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3857 case WINED3DTSS_ADDRESSW :
3859 GLint wrapParm = GL_REPEAT;
3862 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3863 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3864 case D3DTADDRESS_BORDER:
3866 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3867 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3869 /* FIXME: Not right, but better */
3870 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3871 wrapParm = GL_REPEAT;
3875 case D3DTADDRESS_MIRROR:
3877 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3878 wrapParm = GL_MIRRORED_REPEAT_ARB;
3880 /* Unsupported in OpenGL pre-1.4 */
3881 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3882 wrapParm = GL_REPEAT;
3886 case D3DTADDRESS_MIRRORONCE:
3888 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3889 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3891 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3892 wrapParm = GL_REPEAT;
3898 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3899 wrapParm = GL_REPEAT;
3902 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3903 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3904 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3908 case WINED3DTSS_TEXCOORDINDEX :
3910 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3912 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3913 one flag, you can still specify an index value, which the system uses to
3914 determine the texture wrapping mode.
3915 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3916 means use the vertex position (camera-space) as the input texture coordinates
3917 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3918 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3919 to the TEXCOORDINDEX value */
3922 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3924 switch (Value & 0xFFFF0000) {
3925 case D3DTSS_TCI_PASSTHRU:
3926 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3927 glDisable(GL_TEXTURE_GEN_S);
3928 glDisable(GL_TEXTURE_GEN_T);
3929 glDisable(GL_TEXTURE_GEN_R);
3930 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3933 case D3DTSS_TCI_CAMERASPACEPOSITION:
3934 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3935 as the input texture coordinates for this stage's texture transformation. This
3936 equates roughly to EYE_LINEAR */
3938 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3939 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3940 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3941 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3942 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3944 glMatrixMode(GL_MODELVIEW);
3947 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3948 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3949 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3950 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3953 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3954 glEnable(GL_TEXTURE_GEN_S);
3955 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3956 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3957 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3958 glEnable(GL_TEXTURE_GEN_T);
3959 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3960 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3961 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3962 glEnable(GL_TEXTURE_GEN_R);
3963 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3964 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3965 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3969 case D3DTSS_TCI_CAMERASPACENORMAL:
3971 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3972 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3973 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3974 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3975 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3976 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3978 glMatrixMode(GL_MODELVIEW);
3981 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3982 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3983 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3984 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3987 glEnable(GL_TEXTURE_GEN_S);
3988 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3989 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3990 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3991 glEnable(GL_TEXTURE_GEN_T);
3992 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3993 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3994 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3995 glEnable(GL_TEXTURE_GEN_R);
3996 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3997 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3998 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4003 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4005 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4006 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4007 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4008 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4009 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4010 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4012 glMatrixMode(GL_MODELVIEW);
4015 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4016 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4017 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4018 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4021 glEnable(GL_TEXTURE_GEN_S);
4022 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4023 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4024 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4025 glEnable(GL_TEXTURE_GEN_T);
4026 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4027 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4028 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4029 glEnable(GL_TEXTURE_GEN_R);
4030 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4031 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4032 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4037 /* Unhandled types: */
4040 /* ? disable GL_TEXTURE_GEN_n ? */
4041 glDisable(GL_TEXTURE_GEN_S);
4042 glDisable(GL_TEXTURE_GEN_T);
4043 glDisable(GL_TEXTURE_GEN_R);
4044 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4051 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4052 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
4055 case WINED3DTSS_BUMPENVMAT00 :
4056 case WINED3DTSS_BUMPENVMAT01 :
4057 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4059 case WINED3DTSS_BUMPENVMAT10 :
4060 case WINED3DTSS_BUMPENVMAT11 :
4061 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4064 case WINED3DTSS_BUMPENVLSCALE :
4065 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4068 case WINED3DTSS_BUMPENVLOFFSET :
4069 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4072 case WINED3DTSS_RESULTARG :
4073 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4077 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4078 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4086 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4087 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4088 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4089 *pValue = This->updateStateBlock->textureState[Stage][Type];
4096 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4098 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4099 IWineD3DBaseTexture *oldTexture;
4100 BOOL reapplyStates = TRUE;
4101 DWORD reapplyFlags = 0;
4102 INT oldTextureDimensions = -1;
4103 D3DRESOURCETYPE textureType;
4105 oldTexture = This->updateStateBlock->textures[Stage];
4106 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4108 /* Reject invalid texture units */
4109 if (Stage >= GL_LIMITS(textures)) {
4110 TRACE("Attempt to access invalid texture rejected\n");
4111 return D3DERR_INVALIDCALL;
4114 This->updateStateBlock->set.textures[Stage] = TRUE;
4115 This->updateStateBlock->changed.textures[Stage] = TRUE;
4116 This->updateStateBlock->textures[Stage] = pTexture;
4118 /* Handle recording of state blocks */
4119 if (This->isRecordingState) {
4120 TRACE("Recording... not performing anything\n");
4124 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
4128 /* Make appropriate texture active */
4129 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4130 GLACTIVETEXTURE(Stage);
4132 } else if (Stage>0) {
4133 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
4136 /** NOTE: MSDN says that setTexture increases the reference count,
4137 * and the the application nust set the texture back to null (or have a leaky application),
4138 * This means we should pass the refcount upto the parent
4139 *******************************/
4140 if (NULL != oldTexture) {
4142 IUnknown *textureParent;
4143 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4144 IUnknown_Release(textureParent);
4145 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4150 if (NULL != pTexture) {
4151 IUnknown *textureParent;
4152 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4153 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
4155 /* Now setup the texture appropraitly */
4156 textureType = IWineD3DBaseTexture_GetType(pTexture);
4158 if (textureType == D3DRTYPE_TEXTURE) {
4160 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4161 TRACE("Skipping setting texture as old == new\n");
4162 reapplyStates = FALSE;
4166 /* Standard 2D texture */
4167 TRACE("Standard 2d texture\n");
4168 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
4170 /* Load up the texture now */
4171 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
4174 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
4176 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4177 TRACE("Skipping setting texture as old == new\n");
4178 reapplyStates = FALSE;
4182 /* Standard 3D (volume) texture */
4183 TRACE("Standard 3d texture\n");
4184 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
4186 /* Load up the texture now */
4187 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
4190 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
4192 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4193 TRACE("Skipping setting texture as old == new\n");
4194 reapplyStates = FALSE;
4198 /* Standard Cube texture */
4199 TRACE("Standard Cube texture\n");
4200 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
4202 /* Load up the texture now */
4203 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
4207 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
4212 TRACE("Setting to no texture (ie default texture)\n");
4213 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
4214 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
4215 checkGLcall("glBindTexture");
4216 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
4219 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
4220 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4222 glDisable(oldTextureDimensions);
4223 checkGLcall("Disable oldTextureDimensions");
4225 if (This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
4226 glEnable(This->updateStateBlock->textureDimensions[Stage]);
4227 checkGLcall("glEnable new texture dimensions");
4230 /* If Alpha arg1 is texture then handle the special case when there changes between a
4231 texture and no texture - See comments in set_tex_op */
4232 if ((This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4233 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4235 reapplyFlags |= REAPPLY_ALPHAOP;
4240 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4241 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4242 if (reapplyStates) {
4243 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4247 TRACE("Texture now fully setup\n");
4252 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4253 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4254 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4255 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4257 IWineD3DBaseTexture_AddRef(*ppTexture);
4264 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4265 IWineD3DSurface** ppBackBuffer) {
4266 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4267 IWineD3DSwapChain *swapChain;
4270 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4272 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4274 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4275 IWineD3DSwapChain_Release(swapChain);
4277 *ppBackBuffer = NULL;
4282 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4283 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4284 WARN("(%p) : stub, calling idirect3d for now\n", This);
4285 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4288 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4289 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4290 IWineD3DSwapChain *swapChain;
4293 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4295 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4296 IWineD3DSwapChain_Release(swapChain);
4298 FIXME("(%p) Error getting display mode\n", This);
4303 * Stateblock related functions
4306 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4307 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4308 IWineD3DStateBlockImpl *object;
4309 TRACE("(%p)", This);
4310 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4311 if(NULL == object ) {
4312 FIXME("(%p)Error allocating memory for stateblock\n", This);
4313 return E_OUTOFMEMORY;
4315 TRACE("(%p) creted object %p\n", This, object);
4316 object->wineD3DDevice= This;
4317 /** FIXME: object->parent = parent; **/
4318 object->parent = NULL;
4319 object->blockType = D3DSBT_ALL;
4321 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4323 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4324 This->updateStateBlock = object;
4325 This->isRecordingState = TRUE;
4327 TRACE("(%p) recording stateblock %p\n",This , object);
4331 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4332 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4334 if (!This->isRecordingState) {
4335 FIXME("(%p) not recording! returning error\n", This);
4336 *ppStateBlock = NULL;
4337 return D3DERR_INVALIDCALL;
4340 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4341 This->isRecordingState = FALSE;
4342 This->updateStateBlock = This->stateBlock;
4343 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4344 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4345 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4350 * Scene related functions
4352 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4353 /* At the moment we have no need for any functionality at the beginning
4355 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4356 TRACE("(%p) : stub\n", This);
4360 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4361 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4362 TRACE("(%p)\n", This);
4364 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4366 checkGLcall("glFlush");
4368 TRACE("End Scene\n");
4369 if(This->renderTarget != NULL) {
4371 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4372 IUnknown *targetContainer = NULL;
4373 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)) {
4374 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4375 /** always dirtify for now. we must find a better way to see that surface have been modified
4376 (Modifications should will only occur via draw-primitive, but we do need better locking
4377 switching to render-to-texture should remove the overhead though.
4379 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4380 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4381 IWineD3DSurface_PreLoad(This->renderTarget);
4382 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4383 IUnknown_Release(targetContainer);
4385 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4386 /* The surface is stand-alone, so doesn't currently have a context of it's own */
4387 TRACE("(%p) : standalone rendertarget %p\n", This, This->renderTarget);
4388 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4389 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4390 IWineD3DSurface_PreLoad(This->renderTarget);
4391 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4392 IUnknown_Release(targetContainer);
4401 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4402 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4403 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4404 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4405 IWineD3DSwapChain *swapChain = NULL;
4407 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4409 TRACE("(%p) Presenting the frame\n", This);
4411 for(i = 0 ; i < swapchains ; i ++) {
4413 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4414 TRACE("presentinng chain %d, %p\n", i, swapChain);
4415 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4416 IWineD3DSwapChain_Release(swapChain);
4422 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4423 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4424 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4426 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4427 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4428 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4429 GLbitfield glMask = 0;
4430 GLboolean old_ztest;
4431 GLfloat old_z_clear_value;
4432 GLint old_stencil_clear_value;
4433 GLfloat old_color_clear_value[4];
4435 CONST D3DRECT* curRect;
4437 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4438 Count, pRects, Flags, Z, Stencil);
4442 glEnable(GL_SCISSOR_TEST);
4443 checkGLcall("glEnable GL_SCISSOR_TEST");
4445 if (Count > 0 && pRects) {
4451 /* Only set the values up once, as they are not changing */
4452 if (Flags & D3DCLEAR_STENCIL) {
4453 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4454 glClearStencil(Stencil);
4455 checkGLcall("glClearStencil");
4456 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4457 glStencilMask(0xFFFFFFFF);
4460 if (Flags & D3DCLEAR_ZBUFFER) {
4461 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4462 glDepthMask(GL_TRUE);
4463 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4465 checkGLcall("glClearDepth");
4466 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4469 if (Flags & D3DCLEAR_TARGET) {
4470 TRACE("Clearing screen with glClear to color %lx\n", Color);
4471 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4472 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4473 ((Color >> 8) & 0xFF) / 255.0f,
4474 ((Color >> 0) & 0xFF) / 255.0f,
4475 ((Color >> 24) & 0xFF) / 255.0f);
4476 checkGLcall("glClearColor");
4478 /* Clear ALL colors! */
4479 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4480 glMask = glMask | GL_COLOR_BUFFER_BIT;
4483 /* Now process each rect in turn */
4484 for (i = 0; i < Count || i == 0; i++) {
4487 /* Note gl uses lower left, width/height */
4488 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4489 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4490 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4491 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4492 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4493 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4494 checkGLcall("glScissor");
4496 glScissor(This->stateBlock->viewport.X,
4497 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4498 This->stateBlock->viewport.Width,
4499 This->stateBlock->viewport.Height);
4500 checkGLcall("glScissor");
4503 /* Clear the selected rectangle (or full screen) */
4505 checkGLcall("glClear");
4507 /* Step to the next rectangle */
4508 if (curRect) curRect = curRect + sizeof(D3DRECT);
4511 /* Restore the old values (why..?) */
4512 if (Flags & D3DCLEAR_STENCIL) {
4513 glClearStencil(old_stencil_clear_value);
4514 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4516 if (Flags & D3DCLEAR_ZBUFFER) {
4517 glDepthMask(old_ztest);
4518 glClearDepth(old_z_clear_value);
4520 if (Flags & D3DCLEAR_TARGET) {
4521 glClearColor(old_color_clear_value[0],
4522 old_color_clear_value[1],
4523 old_color_clear_value[2],
4524 old_color_clear_value[3]);
4525 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4526 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4527 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4528 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4531 glDisable(GL_SCISSOR_TEST);
4532 checkGLcall("glDisable");
4541 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4542 UINT PrimitiveCount) {
4544 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4545 This->stateBlock->streamIsUP = FALSE;
4547 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4548 debug_d3dprimitivetype(PrimitiveType),
4549 StartVertex, PrimitiveCount);
4550 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4555 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4556 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4557 D3DPRIMITIVETYPE PrimitiveType,
4558 INT baseVIndex, UINT minIndex,
4559 UINT NumVertices,UINT startIndex,UINT primCount) {
4561 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4563 IWineD3DIndexBuffer *pIB;
4564 D3DINDEXBUFFER_DESC IdxBufDsc;
4566 pIB = This->stateBlock->pIndexData;
4567 This->stateBlock->streamIsUP = FALSE;
4569 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4570 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4571 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4573 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4574 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4580 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4581 startIndex, idxStride,
4582 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4588 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4589 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4590 UINT VertexStreamZeroStride) {
4591 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4593 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4594 debug_d3dprimitivetype(PrimitiveType),
4595 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4597 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4599 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4600 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4601 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4602 This->stateBlock->streamIsUP = TRUE;
4603 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4604 This->stateBlock->streamStride[0] = 0;
4605 This->stateBlock->streamSource[0] = NULL;
4607 /*stream zero settings set to null at end, as per the msdn */
4611 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4612 UINT MinVertexIndex,
4613 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4614 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4615 UINT VertexStreamZeroStride) {
4617 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4619 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4620 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4621 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4622 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4624 if (This->stateBlock->streamSource[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->streamSource[0]);
4626 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4632 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4633 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4634 This->stateBlock->streamIsUP = TRUE;
4635 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4637 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4639 /* stream zero settings set to null at end as per the msdn */
4640 This->stateBlock->streamSource[0] = NULL;
4641 This->stateBlock->streamStride[0] = 0;
4642 IWineD3DDevice_SetIndices(iface, NULL, 0);
4647 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4648 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4649 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4650 D3DRESOURCETYPE sourceType;
4651 D3DRESOURCETYPE destinationType;
4652 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4653 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4656 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4657 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4658 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4659 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4660 return D3DERR_INVALIDCALL;
4662 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4664 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4665 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4666 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4668 /* Make sure that the destination texture is loaded */
4669 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4670 TRACE("Loading source texture\n");
4672 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4673 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4674 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4677 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4678 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4680 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4681 return D3DERR_INVALIDCALL;
4683 /** TODO: check that both textures have the same number of levels **/
4685 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4686 return D3DERR_INVALIDCALL;
4688 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4689 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4690 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4696 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4697 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4698 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4699 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4701 TRACE("(%p) : stub\n", This);
4704 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4705 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4707 TRACE("(%p) : stub\n", This);
4711 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4712 IWineD3DSwapChain *swapChain;
4714 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4716 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4717 IWineD3DSwapChain_Release(swapChain);
4722 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4723 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4724 /* return a sensible default */
4726 FIXME("(%p) : stub\n", This);
4730 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4731 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4732 FIXME("(%p) : stub\n", This);
4736 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4737 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4738 FIXME("(%p) : stub\n", This);
4742 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4743 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4744 FIXME("(%p) : stub\n", This);
4748 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4749 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4750 FIXME("(%p) : stub\n", This);
4754 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4755 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4756 FIXME("(%p) : stub\n", This);
4761 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4762 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4763 FIXME("(%p) : stub\n", This);
4768 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4769 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4771 pRasterStatus->InVBlank = TRUE;
4772 pRasterStatus->ScanLine = 0;
4773 FIXME("(%p) : stub\n", This);
4778 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4779 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4780 static BOOL showfixmes = TRUE;
4781 if(nSegments != 0.0f) {
4783 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4790 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4791 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4792 static BOOL showfixmes = TRUE;
4794 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4801 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4802 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4803 /** TODO: remove casts to IWineD3DSurfaceImpl
4804 * NOTE: move code to surface to accomplish this
4805 ****************************************/
4806 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4807 int srcWidth, srcHeight, srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4808 WINED3DFORMAT destFormat, srcFormat;
4810 int destLeft, destTop;
4811 D3DPOOL srcPool, destPool;
4813 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4814 glDescriptor *glDescription = NULL;
4815 GLenum textureDimensions = GL_TEXTURE_2D;
4816 IWineD3DBaseTexture *baseTexture;
4818 WINED3DSURFACE_DESC winedesc;
4820 memset(&winedesc, 0, sizeof(winedesc));
4821 winedesc.Width = &srcSurfaceWidth;
4822 winedesc.Height = &srcSurfaceHeight;
4823 winedesc.Pool = &srcPool;
4824 winedesc.Format = &srcFormat;
4826 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4828 winedesc.Width = &destSurfaceWidth;
4829 winedesc.Height = &destSurfaceHeight;
4830 winedesc.Pool = &destPool;
4831 winedesc.Format = &destFormat;
4832 winedesc.Size = &destSize;
4834 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4836 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
4837 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4838 return D3DERR_INVALIDCALL;
4840 /* TODO: change this to use bindTexture */
4841 /* Make sure the surface is loaded and upto date */
4842 IWineD3DSurface_PreLoad(pDestinationSurface);
4844 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4848 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4849 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4850 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4851 destLeft = pDestPoint ? pDestPoint->x : 0;
4852 destTop = pDestPoint ? pDestPoint->y : 0;
4855 /* This function doesn't support compressed textures
4856 the pitch is just bytesPerPixel * width */
4858 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
4859 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4860 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
4861 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4863 /* TODO DXT formats */
4865 if(pSourceRect != NULL && pSourceRect->top != 0){
4866 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4868 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4870 ,glDescription->level
4875 ,glDescription->glFormat
4876 ,glDescription->glType
4877 ,IWineD3DSurface_GetData(pSourceSurface)
4881 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4882 /* need to lock the surface to get the data */
4883 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4885 /* TODO: Cube and volume support */
4887 /* not a whole row so we have to do it a line at a time */
4889 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4890 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4892 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4894 glTexSubImage2D(glDescription->target
4895 ,glDescription->level
4900 ,glDescription->glFormat
4901 ,glDescription->glType
4902 ,data/* could be quicker using */
4907 } else { /* Full width, so just write out the whole texture */
4909 if (WINED3DFMT_DXT1 == destFormat ||
4910 WINED3DFMT_DXT3 == destFormat ||
4911 WINED3DFMT_DXT5 == destFormat) {
4912 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4913 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4914 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4915 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4916 } if (destFormat != srcFormat) {
4917 FIXME("Updating mixed format compressed texture is not curretly support\n");
4919 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4920 glDescription->level,
4921 glDescription->glFormatInternal,
4926 IWineD3DSurface_GetData(pSourceSurface));
4929 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4934 /* some applications can not handle odd pitches returned by soft non-power2, so we have
4935 to repack the data from pow2Width/Height to expected Width,Height, this makes the
4936 data returned by GetData non-power2 width/height with hardware non-power2
4937 pow2Width/height are set to surface width height, repacking isn't needed so it
4938 doesn't matter which function gets called. */
4939 glTexSubImage2D(glDescription->target
4940 ,glDescription->level
4945 ,glDescription->glFormat
4946 ,glDescription->glType
4947 ,IWineD3DSurface_GetData(pSourceSurface)
4952 checkGLcall("glTexSubImage2D");
4953 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
4954 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
4955 * surface bigger than it needs to be hmm.. */
4956 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
4957 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
4958 IWineD3DBaseTexture_Release(baseTexture);
4961 glDisable(textureDimensions); /* This needs to be managed better.... */
4967 /* Implementation details at http://developer.nvidia.com/attach/6494
4969 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4970 hmm.. no longer supported use
4971 OpenGL evaluators or tessellate surfaces within your application.
4974 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4975 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4976 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4977 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
4978 FIXME("(%p) : Stub\n", This);
4983 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4984 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4985 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4986 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
4987 FIXME("(%p) : Stub\n", This);
4991 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4992 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4993 TRACE("(%p) Handle(%d)\n", This, Handle);
4994 FIXME("(%p) : Stub\n", This);
4998 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
4999 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5001 FIXME("(%p) : stub\n", This);
5005 /* rendertarget and deptth stencil functions */
5006 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5007 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5009 /* FIXME: Implelent RenderTargetIndex >0 */
5010 if(RenderTargetIndex > 0)
5011 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5013 *ppRenderTarget = (IWineD3DSurface *)This->renderTarget;
5014 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5015 /* Note inc ref on returned surface */
5016 if(*ppRenderTarget != NULL)
5017 IWineD3DSurface_AddRef(*ppRenderTarget);
5021 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5022 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5023 *ppZStencilSurface = (IWineD3DSurface *)This->depthStencilBuffer;
5024 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5026 if(*ppZStencilSurface != NULL) {
5027 /* Note inc ref on returned surface */
5028 IWineD3DSurface_AddRef(*ppZStencilSurface);
5033 /* internal static helper functions */
5034 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5035 IWineD3DSurface *RenderSurface);
5037 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
5039 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5040 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5041 HRESULT hr = D3D_OK;
5042 WINED3DVIEWPORT viewport;
5044 TRACE("(%p) Swapping rendertarget\n",This);
5045 if (RenderTargetIndex>0) {
5046 FIXME("(%p) Render targets other than the first are not supported\n",This);
5047 RenderTargetIndex=0;
5050 /* MSDN says that null disables the render target
5051 but a device must always be associated with a render target
5052 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5054 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5057 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5058 FIXME("Trying to set render target 0 to NULL\n");
5059 return D3DERR_INVALIDCALL;
5061 /* TODO: raplce Impl* usage with interface usage */
5062 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5063 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of D3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
5064 return D3DERR_INVALIDCALL;
5066 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5067 * builds, but I think wine counts as a 'debug' build for now.
5068 ******************************/
5069 /* If we are trying to set what we already have, don't bother */
5070 if (pRenderTarget == This->renderTarget) {
5071 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5073 /* Otherwise, set the render target up */
5074 TRACE("clearing renderer\n");
5075 /* IWineD3DDeviceImpl_CleanRender(iface); */
5076 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5077 depending on the renter target implementation being used.
5078 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5079 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5080 stencil buffer and incure an extra memory overhead */
5081 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5084 if (SUCCEEDED(hr)) {
5085 /* Finally, reset the viewport as the MSDN states. */
5086 /* TODO: Replace impl usage */
5087 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5088 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5091 viewport.MaxZ = 1.0f;
5092 viewport.MinZ = 0.0f;
5093 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5095 FIXME("Unknown error setting the render target\n");
5100 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5101 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5102 HRESULT hr = D3D_OK;
5103 WINED3DVIEWPORT viewport;
5104 IWineD3DSurface *tmp;
5106 TRACE("(%p) Swapping z-buffer\n",This);
5108 if (pNewZStencil == This->stencilBufferTarget) {
5109 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5111 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5112 * depending on the renter target implementation being used.
5113 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5114 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5115 * stencil buffer and incure an extra memory overhead
5116 ******************************************************/
5119 tmp = This->stencilBufferTarget;
5120 This->stencilBufferTarget = pNewZStencil;
5121 /* should we be calling the parent or the wined3d surface? */
5122 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5123 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5125 /** TODO: glEnable/glDisable on depth/stencil depending on
5126 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5127 **********************************************************/
5130 if (SUCCEEDED(hr)) {
5131 /* Finally, reset the viewport as the MSDN states.*/
5132 /* TODO: get ridd of Impl usage */
5133 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5134 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5137 viewport.MaxZ = 1.0f;
5138 viewport.MinZ = 0.0f;
5139 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5146 /* Internal functions not in DirectX */
5147 /** TODO: move this off to the opengl context manager
5148 *(the swapchain doesn't need to know anything about offscreen rendering!)
5149 ****************************************************/
5151 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5153 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5155 TRACE("(%p), %p\n", This, swapchain);
5157 if (swapchain->win != swapchain->drawable) {
5158 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
5160 if (swapchain->glCtx != swapchain->render_ctx) {
5161 FIXME("Destroying context %p \n", swapchain->render_ctx);
5162 glXDestroyContext(swapchain->display, swapchain->render_ctx);
5165 FIXME("glXDestroyPbuffer %ld \n", swapchain->drawable);
5166 glXDestroyPbuffer(swapchain->display, swapchain->drawable);
5169 /* Set everything back the way it ws */
5170 swapchain->render_ctx = swapchain->glCtx;
5171 swapchain->drawable = swapchain->win;
5176 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5177 * the functionality needs splitting up so that we don't do more than we should do.
5178 * this only seems to impact performance a little.
5179 ******************************/
5180 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5181 IWineD3DSurface *RenderSurface) {
5182 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5183 #ifndef USE_RENDER_MANAGER
5185 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5186 HRESULT ret = D3DERR_INVALIDCALL;
5188 * Currently only active for GLX >= 1.3
5189 * for others versions we'll have to use GLXPixmaps
5191 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5192 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5193 * so only check OpenGL version
5194 * ..........................
5195 * I don't believe that it is a problem with NVidia headers,
5196 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5197 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5199 * Your application will report GLX version 1.2 on glXQueryVersion.
5200 * However, it is safe to call the GLX 1.3 functions as described below.
5202 #if defined(GL_VERSION_1_3)
5204 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5205 GLXFBConfig* cfgs = NULL;
5209 IWineD3DSwapChain *currentSwapchain;
5210 IWineD3DSwapChainImpl *swapchain;
5211 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5212 * but switch them off if the StencilSurface is set to NULL
5213 ** *********************************************************/
5214 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5215 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5217 UINT Width = ((IWineD3DSurfaceImpl *) RenderSurface)->currentDesc.Width;
5218 UINT Height = ((IWineD3DSurfaceImpl *) RenderSurface)->currentDesc.Height;
5220 IWineD3DSurface *tmp;
5223 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5224 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5227 #define PUSH1(att) attribs[nAttribs++] = (att);
5228 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5230 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5232 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5233 IWineD3DSwapChainImpl *impSwapChain;
5234 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5235 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5236 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5241 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5242 PUSH2(GLX_X_RENDERABLE, TRUE);
5243 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5244 TRACE("calling makeglcfg\n");
5245 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5250 TRACE("calling chooseFGConfig\n");
5251 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5254 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5255 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5256 why we failed and only show this message once! */
5257 MESSAGE("Failed to find exact match, finding alternative but you may suffer performance issues, try changing xfree's depth to match the requested depth\n"); /**/
5259 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5260 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5261 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5262 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5263 TRACE("calling makeglcfg\n");
5264 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5266 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5273 for (i = 0; i < nCfgs; ++i) {
5274 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5275 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5276 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5280 if (NULL != This->renderTarget) {
5283 vcheckGLcall("glFlush");
5284 /** This is only useful if the old render target was a swapchain,
5285 * we need to supercede this with a function that displays
5286 * the current buffer on the screen. This is easy to do in glx1.3 but
5287 * we need to do copy-write pixels in glx 1.2.
5288 ************************************************/
5289 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5291 printf("Hit Enter to get next frame ...\n");
5296 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5297 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5298 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5302 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5303 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5304 **********************************************************************/
5305 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5306 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5307 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5308 TRACE("making swapchain active\n");
5309 if (RenderSurface != This->renderTarget) {
5310 if (RenderSurface == swapchain->backBuffer) {
5312 /* This could be flagged so that some operations work directly with the front buffer */
5313 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5315 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5317 TRACE("Error in setting current context: context %p drawable %ld !\n",
5318 impSwapChain->glCtx, impSwapChain->win);
5322 #if 0 /* TODO: apply the state block to the 'possibly' new context. */
5324 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5325 oldUpdateStateBlock = This->updateStateBlock;
5326 oldRecording= This->isRecordingState;
5327 This->isRecordingState = FALSE;
5328 This->updateStateBlock = This->stateBlock;
5329 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5331 This->isRecordingState = oldRecording;
5332 This->updateStateBlock = oldUpdateStateBlock;
5335 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5337 checkGLcall("glXMakeContextCurrent");
5339 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5344 (((IWineD3DSwapChainImpl *)currentSwapchain)->drawable == ((IWineD3DSwapChainImpl *)currentSwapchain)->win
5345 || BackBufferFormat != ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Format
5346 || (Width > ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width
5347 || Height > ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height))) {
5349 /** ********************************************************************
5350 * This code is far too leaky to be useful. IWineD3DDeviceImpl_CleanRender
5351 * doesn't seem to work properly and creating a new context every time is 'extremely' overkill.
5352 * The code does however work, and should be moved to a context manager to
5353 * manage caching of pbuffers or render to texture are appropriate.
5355 * There are some real speed vs compatibility issues here:
5356 * we should really use a new context for every texture, but that eats ram.
5357 * we should also be restoring the texture to the pbuffer but that eats CPU
5358 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5359 * but if this means reusing the display backbuffer then we need to make sure that
5360 * states are correctly preserved.
5361 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5362 * and gain a good performance increase at the cost of compatibility.
5363 * I would suggest that, when this is the case, a user configurable flag be made
5364 * available, allowing the user to choose the best emulated experience for them.
5365 *********************************************************************/
5368 * TODO: support for faces of cube textures, possibly volumes
5369 * (this should be easy for ATI as I have examples)
5372 GLXContext newContext;
5373 Drawable newDrawable;
5374 XVisualInfo *visinfo;
5376 TRACE("making new buffer\n");
5378 PUSH2(GLX_PBUFFER_WIDTH, Width);
5379 PUSH2(GLX_PBUFFER_HEIGHT, Height);
5381 #if 0 /* ATI render to texture support */
5382 PUSH2(GLX_LARGEST_PBUFFER, True);/* This is ignored by ATI */
5383 PUSH2(GLX_TEXTURE_FORMAT_ATI, GLX_TEXTURE_RGBA_ATI);
5384 PUSH2(GLX_TEXTURE_TARGET_ATI, cubemap? GLX_TEXTURE_CUBE_MAP_ATI : GLX_TEXTURE_2D_ATI);
5385 PUSH2(GLX_MIPMAP_TEXTURE_ATI, mipmapped? True : False);
5389 /* TODO: discardable Pbuffer */
5390 PUSH2(GLX_PRESERVED_CONTENTS, FALSE);
5394 newDrawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5396 /** ****************************************
5397 *GLX1.3 isn't supported by XFree 'yet' untill that point ATI emulates pBuffers
5399 * In future releases, we may provide the calls glXCreateNewContext,
5400 * glXQueryDrawable and glXMakeContextCurrent.
5401 * so until then we have to use glXGetVisualFromFBConfig &co..
5402 ********************************************/
5405 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5407 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5409 newContext = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5412 /* Make sure that the sorface exists as a glTexture */
5413 IWineD3DSurface_PreLoad(RenderSurface);
5415 newContext = glXCreateNewContext(impSwapChain->display, cfgs[0], GLX_RGBA_TYPE, impSwapChain->glCtx, TRUE);
5417 if (NULL == newContext) {
5418 ERR("cannot create glxContext\n");
5420 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5421 FIXME("Created context %p drawable %ld \n", newContext, newDrawable);
5423 if (glXMakeCurrent(impSwapChain->display, newDrawable, newContext) == False) {
5425 TRACE("Error in setting current context: context %p drawable %ld\n", newContext, newDrawable);
5428 /* TODO: find out what of the current context needs to be coppied accross */
5430 checkGLcall("glXMakeContextCurrent");
5432 /* clean renderer should become part of the context manager so I'm not goint to put in in SwapChain just to remove it */
5433 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5434 /** TODO: We may need to copy the bits into the buffer,
5435 * this should !!ONLY!! be done if an operation is performed on the target
5436 * without it being cleared and the buffer is not discardable.
5437 * (basically only bother preserving the contents if there's a possibility that it will be reused)
5438 ** *********************************************************************/
5439 impSwapChain->drawable = newDrawable;
5440 impSwapChain->render_ctx = newContext;
5446 /* clean up the current rendertargets swapchain (if it belonged to one) */
5447 if (currentSwapchain != NULL) {
5448 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5451 /* Were done with the opengl context management, setup the rendertargets */
5453 tmp = This->renderTarget;
5454 This->renderTarget = RenderSurface;
5455 IWineD3DSurface_AddRef(This->renderTarget);
5456 IWineD3DSurface_Release(tmp);
5462 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5463 /* Check that the container is not a swapchain member */
5465 IWineD3DSwapChain *tmpSwapChain;
5466 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5467 This->renderUpsideDown = TRUE;
5469 This->renderUpsideDown = FALSE;
5470 IWineD3DSwapChain_Release(tmpSwapChain);
5472 /* Force updating the cull mode */
5473 TRACE("setting render state\n");
5474 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5475 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5477 /* Force updating projection matrix */
5478 This->last_was_rhw = FALSE;
5479 This->proj_valid = FALSE;
5487 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5488 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5493 if ( NULL != impSwapChain) {
5494 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5501 IWineD3DSurface *tmp;
5502 /* This should be handled outside of this function */
5503 tmp = This->renderTarget;
5504 This->renderTarget = RenderSurface;
5505 IWineD3DSurface_AddRef(This->renderTarget);
5506 IWineD3DSurface_Release( tmp);
5507 tmp = This->stencilBufferTarget;
5508 This->stencilBufferTarget = StencilSurface;
5515 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5516 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5517 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5518 /* TODO: the use of Impl is deprecated. */
5519 /* some basic validation checks */
5520 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5522 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5524 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5525 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5526 return D3DERR_INVALIDCALL;
5528 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5529 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5530 return D3DERR_INVALIDCALL;
5532 /* TODO: make the cursor 'real' */
5534 This->xHotSpot = XHotSpot;
5535 This->yHotSpot = YHotSpot;
5540 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5541 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5542 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5544 This->xScreenSpace = XScreenSpace;
5545 This->yScreenSpace = YScreenSpace;
5551 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5552 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5553 TRACE("(%p) : visible(%d)\n", This, bShow);
5555 This->bCursorVisible = bShow;
5560 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5561 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5562 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5567 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5568 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5569 /** FIXME: Resource tracking needs to be done,
5570 * The closes we can do to this is set the priorities of all managed textures low
5571 * and then reset them.
5572 ***********************************************************/
5573 FIXME("(%p) : stub\n", This);
5577 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5578 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5579 /** FIXME: Resource trascking needs to be done.
5580 * in effect this pulls all non only default
5581 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5582 * and should clear down the context and set it up according to pPresentationParameters
5583 ***********************************************************/
5584 FIXME("(%p) : stub\n", This);
5588 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5590 /** FIXME: always true at the moment **/
5591 if(bEnableDialogs == FALSE) {
5592 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5598 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5599 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5601 FIXME("(%p) : stub\n", This);
5602 /* Setup some reasonable defaults */
5603 pParameters->AdapterOrdinal = 0; /* always for now */
5604 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5605 pParameters->hFocusWindow = 0;
5606 pParameters->BehaviorFlags =0;
5610 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5611 IWineD3DSwapChain *swapchain;
5612 HRESULT hrc = D3D_OK;
5614 TRACE("Relaying to swapchain\n");
5616 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5617 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5618 IWineD3DSwapChain_Release(swapchain);
5623 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5624 IWineD3DSwapChain *swapchain;
5625 HRESULT hrc = D3D_OK;
5627 TRACE("Relaying to swapchain\n");
5629 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5630 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5631 IWineD3DSwapChain_Release(swapchain);
5636 /**********************************************************
5637 * IWineD3DDevice VTbl follows
5638 **********************************************************/
5640 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5642 /*** IUnknown methods ***/
5643 IWineD3DDeviceImpl_QueryInterface,
5644 IWineD3DDeviceImpl_AddRef,
5645 IWineD3DDeviceImpl_Release,
5646 /*** IWineD3DDevice methods ***/
5647 IWineD3DDeviceImpl_GetParent,
5648 /*** Creation methods**/
5649 IWineD3DDeviceImpl_CreateVertexBuffer,
5650 IWineD3DDeviceImpl_CreateIndexBuffer,
5651 IWineD3DDeviceImpl_CreateStateBlock,
5652 IWineD3DDeviceImpl_CreateSurface,
5653 IWineD3DDeviceImpl_CreateTexture,
5654 IWineD3DDeviceImpl_CreateVolumeTexture,
5655 IWineD3DDeviceImpl_CreateVolume,
5656 IWineD3DDeviceImpl_CreateCubeTexture,
5657 IWineD3DDeviceImpl_CreateQuery,
5658 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5659 IWineD3DDeviceImpl_CreateVertexDeclaration,
5660 IWineD3DDeviceImpl_CreateVertexShader,
5661 IWineD3DDeviceImpl_CreatePixelShader,
5663 /*** Odd functions **/
5664 IWineD3DDeviceImpl_EvictManagedResources,
5665 IWineD3DDeviceImpl_GetAvailableTextureMem,
5666 IWineD3DDeviceImpl_GetBackBuffer,
5667 IWineD3DDeviceImpl_GetCreationParameters,
5668 IWineD3DDeviceImpl_GetDeviceCaps,
5669 IWineD3DDeviceImpl_GetDirect3D,
5670 IWineD3DDeviceImpl_GetDisplayMode,
5671 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5672 IWineD3DDeviceImpl_GetRasterStatus,
5673 IWineD3DDeviceImpl_GetSwapChain,
5674 IWineD3DDeviceImpl_Reset,
5675 IWineD3DDeviceImpl_SetDialogBoxMode,
5676 IWineD3DDeviceImpl_SetCursorProperties,
5677 IWineD3DDeviceImpl_SetCursorPosition,
5678 IWineD3DDeviceImpl_ShowCursor,
5679 IWineD3DDeviceImpl_TestCooperativeLevel,
5680 /*** Getters and setters **/
5681 IWineD3DDeviceImpl_SetClipPlane,
5682 IWineD3DDeviceImpl_GetClipPlane,
5683 IWineD3DDeviceImpl_SetClipStatus,
5684 IWineD3DDeviceImpl_GetClipStatus,
5685 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5686 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5687 IWineD3DDeviceImpl_SetDepthStencilSurface,
5688 IWineD3DDeviceImpl_GetDepthStencilSurface,
5689 IWineD3DDeviceImpl_SetFVF,
5690 IWineD3DDeviceImpl_GetFVF,
5691 IWineD3DDeviceImpl_SetGammaRamp,
5692 IWineD3DDeviceImpl_GetGammaRamp,
5693 IWineD3DDeviceImpl_SetIndices,
5694 IWineD3DDeviceImpl_GetIndices,
5695 IWineD3DDeviceImpl_SetLight,
5696 IWineD3DDeviceImpl_GetLight,
5697 IWineD3DDeviceImpl_SetLightEnable,
5698 IWineD3DDeviceImpl_GetLightEnable,
5699 IWineD3DDeviceImpl_SetMaterial,
5700 IWineD3DDeviceImpl_GetMaterial,
5701 IWineD3DDeviceImpl_SetNPatchMode,
5702 IWineD3DDeviceImpl_GetNPatchMode,
5703 IWineD3DDeviceImpl_SetPaletteEntries,
5704 IWineD3DDeviceImpl_GetPaletteEntries,
5705 IWineD3DDeviceImpl_SetPixelShader,
5706 IWineD3DDeviceImpl_GetPixelShader,
5707 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5708 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5709 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5710 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5711 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5712 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5713 IWineD3DDeviceImpl_SetRenderState,
5714 IWineD3DDeviceImpl_GetRenderState,
5715 IWineD3DDeviceImpl_SetRenderTarget,
5716 IWineD3DDeviceImpl_GetRenderTarget,
5717 IWineD3DDeviceImpl_SetSamplerState,
5718 IWineD3DDeviceImpl_GetSamplerState,
5719 IWineD3DDeviceImpl_SetScissorRect,
5720 IWineD3DDeviceImpl_GetScissorRect,
5721 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5722 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5723 IWineD3DDeviceImpl_SetStreamSource,
5724 IWineD3DDeviceImpl_GetStreamSource,
5725 IWineD3DDeviceImpl_SetStreamSourceFreq,
5726 IWineD3DDeviceImpl_GetStreamSourceFreq,
5727 IWineD3DDeviceImpl_SetTexture,
5728 IWineD3DDeviceImpl_GetTexture,
5729 IWineD3DDeviceImpl_SetTextureStageState,
5730 IWineD3DDeviceImpl_GetTextureStageState,
5731 IWineD3DDeviceImpl_SetTransform,
5732 IWineD3DDeviceImpl_GetTransform,
5733 IWineD3DDeviceImpl_SetVertexDeclaration,
5734 IWineD3DDeviceImpl_GetVertexDeclaration,
5735 IWineD3DDeviceImpl_SetVertexShader,
5736 IWineD3DDeviceImpl_GetVertexShader,
5737 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5738 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5739 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5740 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5741 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5742 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5743 IWineD3DDeviceImpl_SetViewport,
5744 IWineD3DDeviceImpl_GetViewport,
5745 IWineD3DDeviceImpl_MultiplyTransform,
5746 IWineD3DDeviceImpl_ValidateDevice,
5747 IWineD3DDeviceImpl_ProcessVertices,
5748 /*** State block ***/
5749 IWineD3DDeviceImpl_BeginStateBlock,
5750 IWineD3DDeviceImpl_EndStateBlock,
5751 /*** Scene management ***/
5752 IWineD3DDeviceImpl_BeginScene,
5753 IWineD3DDeviceImpl_EndScene,
5754 IWineD3DDeviceImpl_Present,
5755 IWineD3DDeviceImpl_Clear,
5757 IWineD3DDeviceImpl_DrawPrimitive,
5758 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5759 IWineD3DDeviceImpl_DrawPrimitiveUP,
5760 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5761 IWineD3DDeviceImpl_DrawRectPatch,
5762 IWineD3DDeviceImpl_DrawTriPatch,
5763 IWineD3DDeviceImpl_DeletePatch,
5764 IWineD3DDeviceImpl_ColorFill,
5765 IWineD3DDeviceImpl_UpdateTexture,
5766 IWineD3DDeviceImpl_UpdateSurface,
5767 IWineD3DDeviceImpl_StretchRect,
5768 IWineD3DDeviceImpl_GetRenderTargetData,
5769 IWineD3DDeviceImpl_GetFrontBufferData,
5770 /*** Internal use IWineD3DDevice methods ***/
5771 IWineD3DDeviceImpl_SetupTextureStates
5775 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5776 WINED3DRS_ALPHABLENDENABLE ,
5777 WINED3DRS_ALPHAFUNC ,
5778 WINED3DRS_ALPHAREF ,
5779 WINED3DRS_ALPHATESTENABLE ,
5781 WINED3DRS_COLORWRITEENABLE ,
5782 WINED3DRS_DESTBLEND ,
5783 WINED3DRS_DITHERENABLE ,
5784 WINED3DRS_FILLMODE ,
5785 WINED3DRS_FOGDENSITY ,
5787 WINED3DRS_FOGSTART ,
5788 WINED3DRS_LASTPIXEL ,
5789 WINED3DRS_SHADEMODE ,
5790 WINED3DRS_SRCBLEND ,
5791 WINED3DRS_STENCILENABLE ,
5792 WINED3DRS_STENCILFAIL ,
5793 WINED3DRS_STENCILFUNC ,
5794 WINED3DRS_STENCILMASK ,
5795 WINED3DRS_STENCILPASS ,
5796 WINED3DRS_STENCILREF ,
5797 WINED3DRS_STENCILWRITEMASK ,
5798 WINED3DRS_STENCILZFAIL ,
5799 WINED3DRS_TEXTUREFACTOR ,
5810 WINED3DRS_ZWRITEENABLE
5813 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5814 WINED3DTSS_ADDRESSW ,
5815 WINED3DTSS_ALPHAARG0 ,
5816 WINED3DTSS_ALPHAARG1 ,
5817 WINED3DTSS_ALPHAARG2 ,
5818 WINED3DTSS_ALPHAOP ,
5819 WINED3DTSS_BUMPENVLOFFSET ,
5820 WINED3DTSS_BUMPENVLSCALE ,
5821 WINED3DTSS_BUMPENVMAT00 ,
5822 WINED3DTSS_BUMPENVMAT01 ,
5823 WINED3DTSS_BUMPENVMAT10 ,
5824 WINED3DTSS_BUMPENVMAT11 ,
5825 WINED3DTSS_COLORARG0 ,
5826 WINED3DTSS_COLORARG1 ,
5827 WINED3DTSS_COLORARG2 ,
5828 WINED3DTSS_COLOROP ,
5829 WINED3DTSS_RESULTARG ,
5830 WINED3DTSS_TEXCOORDINDEX ,
5831 WINED3DTSS_TEXTURETRANSFORMFLAGS
5834 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5835 WINED3DSAMP_ADDRESSU ,
5836 WINED3DSAMP_ADDRESSV ,
5837 WINED3DSAMP_ADDRESSW ,
5838 WINED3DSAMP_BORDERCOLOR ,
5839 WINED3DSAMP_MAGFILTER ,
5840 WINED3DSAMP_MINFILTER ,
5841 WINED3DSAMP_MIPFILTER ,
5842 WINED3DSAMP_MIPMAPLODBIAS ,
5843 WINED3DSAMP_MAXMIPLEVEL ,
5844 WINED3DSAMP_MAXANISOTROPY ,
5845 WINED3DSAMP_SRGBTEXTURE ,
5846 WINED3DSAMP_ELEMENTINDEX
5849 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5851 WINED3DRS_AMBIENTMATERIALSOURCE ,
5852 WINED3DRS_CLIPPING ,
5853 WINED3DRS_CLIPPLANEENABLE ,
5854 WINED3DRS_COLORVERTEX ,
5855 WINED3DRS_DIFFUSEMATERIALSOURCE ,
5856 WINED3DRS_EMISSIVEMATERIALSOURCE ,
5857 WINED3DRS_FOGDENSITY ,
5859 WINED3DRS_FOGSTART ,
5860 WINED3DRS_FOGTABLEMODE ,
5861 WINED3DRS_FOGVERTEXMODE ,
5862 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
5863 WINED3DRS_LIGHTING ,
5864 WINED3DRS_LOCALVIEWER ,
5865 WINED3DRS_MULTISAMPLEANTIALIAS ,
5866 WINED3DRS_MULTISAMPLEMASK ,
5867 WINED3DRS_NORMALIZENORMALS ,
5868 WINED3DRS_PATCHEDGESTYLE ,
5869 WINED3DRS_POINTSCALE_A ,
5870 WINED3DRS_POINTSCALE_B ,
5871 WINED3DRS_POINTSCALE_C ,
5872 WINED3DRS_POINTSCALEENABLE ,
5873 WINED3DRS_POINTSIZE ,
5874 WINED3DRS_POINTSIZE_MAX ,
5875 WINED3DRS_POINTSIZE_MIN ,
5876 WINED3DRS_POINTSPRITEENABLE ,
5877 WINED3DRS_RANGEFOGENABLE ,
5878 WINED3DRS_SPECULARMATERIALSOURCE ,
5879 WINED3DRS_TWEENFACTOR ,
5880 WINED3DRS_VERTEXBLEND
5883 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5884 WINED3DTSS_TEXCOORDINDEX ,
5885 WINED3DTSS_TEXTURETRANSFORMFLAGS
5888 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5889 WINED3DSAMP_DMAPOFFSET