Tidy up some of the formatting in drawprim and add missing strided
[wine] / dlls / wined3d / device.c
1 /*
2  * IWineD3DDevice implementation
3  *
4  * Copyright 2002-2005 Jason Edmeades
5  * Copyright 2003-2004 Raphael Junqueira
6  * Copyright 2004 Christian Costa
7  * Copyright 2005 Oliver Stieber
8  *
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.
13  *
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.
18  *
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
22  */
23
24 #include "config.h"
25 #include "wined3d_private.h"
26
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
32
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
36 {
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 */
40 };
41
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
44 {
45     Display *display;
46     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
47
48     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49                     sizeof(display), (LPSTR)&display )) display = NULL;
50     return display;
51 }
52
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
55
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support     = TRUE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
61
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
64
65
66 /* helper macros */
67 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
68
69 #define D3DCREATEOBJECTINSTANCE(object, type) { \
70     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
71     D3DMEMCHECK(object, pp##type); \
72     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
73     object->wineD3DDevice = This; \
74     object->parent       = parent; \
75     object->ref          = 1; \
76     *pp##type = (IWineD3D##type *) object; \
77 }
78
79 #define  D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
80     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
81     D3DMEMCHECK(object, pp##type); \
82     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
83     object->resource.wineD3DDevice   = This; \
84     object->resource.parent          = parent; \
85     object->resource.resourceType    = d3dtype; \
86     object->resource.ref             = 1; \
87     object->resource.pool            = Pool; \
88     object->resource.format          = Format; \
89     object->resource.usage           = Usage; \
90     object->resource.size            = _size; \
91     /* Check that we have enough video ram left */ \
92     if (Pool == D3DPOOL_DEFAULT) { \
93         if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
94             WARN("Out of 'bogus' video memory\n"); \
95             HeapFree(GetProcessHeap(),0,object); \
96             *pp##type = NULL; \
97             return D3DERR_OUTOFVIDEOMEMORY; \
98         } \
99         globalChangeGlRam(_size); \
100     } \
101     object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
102     if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
103         FIXME("Out of memory!\n"); \
104         HeapFree(GetProcessHeap(), 0, object); \
105         *pp##type = NULL; \
106         return D3DERR_OUTOFVIDEOMEMORY; \
107     } \
108     *pp##type = (IWineD3D##type *) object; \
109     IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
110     TRACE("(%p) : Created resource %p\n", This, object); \
111 }
112
113 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
114     _basetexture.levels     = Levels; \
115     _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
116     _basetexture.LOD        = 0; \
117     _basetexture.dirty      = TRUE; \
118 }
119
120 /**********************************************************
121  * Global variable / Constants follow
122  **********************************************************/
123 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
124
125 /**********************************************************
126  * Utility functions follow
127  **********************************************************/
128 /* Convert the D3DLIGHT properties into equivalent gl lights */
129 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
130
131     float quad_att;
132     float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
133     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
134
135     /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
136     glMatrixMode(GL_MODELVIEW);
137     glPushMatrix();
138     glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
139
140     /* Diffuse: */
141     colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
142     colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
143     colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
144     colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
145     glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
146     checkGLcall("glLightfv");
147
148     /* Specular */
149     colRGBA[0] = lightInfo->OriginalParms.Specular.r;
150     colRGBA[1] = lightInfo->OriginalParms.Specular.g;
151     colRGBA[2] = lightInfo->OriginalParms.Specular.b;
152     colRGBA[3] = lightInfo->OriginalParms.Specular.a;
153     glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
154     checkGLcall("glLightfv");
155
156     /* Ambient */
157     colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
158     colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
159     colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
160     colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
161     glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
162     checkGLcall("glLightfv");
163
164     /* Attenuation - Are these right? guessing... */
165     glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
166     checkGLcall("glLightf");
167     glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
168     checkGLcall("glLightf");
169
170     if ((lightInfo->OriginalParms.Range * lightInfo->OriginalParms.Range) != 0 ) {
171         quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
172     } else {
173         quad_att = 0; /*  0 or  MAX?  (0 seems to be ok) */
174     }
175
176     if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
177     glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
178     checkGLcall("glLightf");
179
180     switch (lightInfo->OriginalParms.Type) {
181     case D3DLIGHT_POINT:
182         /* Position */
183         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
184         checkGLcall("glLightfv");
185         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
186         checkGLcall("glLightf");
187         /* FIXME: Range */
188         break;
189
190     case D3DLIGHT_SPOT:
191         /* Position */
192         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
193         checkGLcall("glLightfv");
194         /* Direction */
195         glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
196         checkGLcall("glLightfv");
197         glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
198         checkGLcall("glLightf");
199         glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
200         checkGLcall("glLightf");
201         /* FIXME: Range */
202         break;
203
204     case D3DLIGHT_DIRECTIONAL:
205         /* Direction */
206         glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
207         checkGLcall("glLightfv");
208         glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
209         checkGLcall("glLightf");
210         glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
211         checkGLcall("glLightf");
212         break;
213
214     default:
215         FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
216     }
217
218     /* Restore the modelview matrix */
219     glPopMatrix();
220 }
221
222 /* Apply the current values to the specified texture stage */
223 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
224     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
225     int i = 0;
226     float col[4];
227     BOOL changeTexture = TRUE;
228
229     TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
230     for (i = 1; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
231
232         BOOL skip = FALSE;
233
234         switch (i) {
235         /* Performance: For texture states where multiples effect the outcome, only bother
236               applying the last one as it will pick up all the other values                */
237         case WINED3DTSS_COLORARG0:  /* Will be picked up when setting color op */
238         case WINED3DTSS_COLORARG1:  /* Will be picked up when setting color op */
239         case WINED3DTSS_COLORARG2:  /* Will be picked up when setting color op */
240         case WINED3DTSS_ALPHAARG0:  /* Will be picked up when setting alpha op */
241         case WINED3DTSS_ALPHAARG1:  /* Will be picked up when setting alpha op */
242         case WINED3DTSS_ALPHAARG2:  /* Will be picked up when setting alpha op */
243            skip = TRUE;
244            break;
245
246         /* Performance: If the texture states only impact settings for the texture unit
247              (compared to the texture object) then there is no need to reapply them. The
248              only time they need applying is the first time, since we cheat and put the
249              values into the stateblock without applying.
250              Per-texture unit: texture function (eg. combine), ops and args
251                                texture env color
252                                texture generation settings
253            Note: Due to some special conditions there may be a need to do particular ones
254              of these, which is what the Flags allows                                     */
255         case WINED3DTSS_COLOROP:
256         case WINED3DTSS_TEXCOORDINDEX:
257             if (!(Flags == REAPPLY_ALL)) skip=TRUE;
258             break;
259
260         case WINED3DTSS_ALPHAOP:
261             if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
262             break;
263
264         default:
265             skip = FALSE;
266         }
267
268         if (skip == FALSE) {
269            /* Performance: Only change to this texture if we have to */
270            if (changeTexture) {
271                /* Make appropriate texture active */
272                if (GL_SUPPORT(ARB_MULTITEXTURE)) {
273                    GLACTIVETEXTURE(Stage);
274                 } else if (Stage > 0) {
275                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
276                 }
277                 changeTexture = FALSE;
278            }
279
280            /* Now apply the change */
281            IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
282         }
283     }
284
285     /* apply the sampler states to the texture */
286     for (i = 1; i <= WINED3D_HIGHEST_SAMPLER_STATE;i++) {
287       IWineD3DDevice_SetSamplerState(iface, Stage, i, This->stateBlock->samplerState[Stage][i]);
288     }
289
290     /* Note the D3DRS value applies to all textures, but GL has one
291      *  per texture, so apply it now ready to be used!
292      */
293     D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294     glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
295     checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
296
297     TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
298 }
299
300 /**********************************************************
301  * IUnknown parts follows
302  **********************************************************/
303
304 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
305 {
306     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
307     /* FIXME: This needs to extend an IWineD3DBaseObject */
308
309     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
310     if (IsEqualGUID(riid, &IID_IUnknown)
311         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
312         IUnknown_AddRef(iface);
313         *ppobj = This;
314         return D3D_OK;
315     }
316
317     return E_NOINTERFACE;
318 }
319
320 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
321     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
322     ULONG refCount = InterlockedIncrement(&This->ref);
323
324     TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
325     return refCount;
326 }
327
328 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
329     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
330     ULONG refCount = InterlockedDecrement(&This->ref);
331
332     TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
333
334     if (!refCount) {
335         /* TODO: Clean up all the surfaces and textures! */
336         /* FIXME: Create targets and state blocks in d3d8 */
337         if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
338             /* NOTE: You must release the parent if the object was created via a callback
339             ** ***************************/
340             IUnknown* swapChainParent;
341
342             /* NOTE: Don't release swapchain 0 here, it's 'special' */
343             SwapChainList *nextSwapchain = This->swapchains;
344             if (nextSwapchain != NULL) {
345                 nextSwapchain = nextSwapchain->next;
346             } else {
347                 WARN("Expected to find the implicite swapchain\n");
348             }
349
350             /* release all the other swapchains */
351             while (nextSwapchain != NULL) {
352                 SwapChainList *prevSwapchain = nextSwapchain;
353                 nextSwapchain = nextSwapchain->next;
354                 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
355                 /* NOTE: no need to free the list element, it will be done by the release callback
356                    HeapFree(GetProcessHeap(), 0, prevSwapchain); */
357             }
358
359             if (This->stateBlock != NULL) {
360                 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
361             }
362
363             if (This->swapchains != NULL) {
364                 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release it's parent now */
365                 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
366                 IUnknown_Release(swapChainParent);           /* once for the get parent */
367                 if (IUnknown_Release(swapChainParent)  > 0) {  /* the second time for when it was created */
368                     FIXME("(%p) Something's still holding the implicite swapchain\n", This);
369                 }
370             }
371
372         }
373         IWineD3D_Release(This->wineD3D);
374         HeapFree(GetProcessHeap(), 0, This);
375     }
376     return refCount;
377 }
378
379 /**********************************************************
380  * IWineD3DDevice implementation follows
381  **********************************************************/
382 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
383     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
384     *pParent = This->parent;
385     IUnknown_AddRef(This->parent);
386     return D3D_OK;
387 }
388
389 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage, 
390                              DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
391                              IUnknown *parent) {
392     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
393     IWineD3DVertexBufferImpl *object;
394     WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
395     D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
396     
397     /*TODO: use VBO's */
398     if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
399         object->resource.allocatedMemory  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
400     }
401     object->fvf = FVF;
402
403     TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
404     *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
405
406     return D3D_OK;
407 }
408
409 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage, 
410                                                     WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
411                                                     HANDLE *sharedHandle, IUnknown *parent) {
412     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
413     IWineD3DIndexBufferImpl *object;
414     TRACE("(%p) Creating index buffer\n", This);
415     
416     /* Allocate the storage for the device */
417     D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
418     
419     /*TODO: use VBO's */
420     if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
421         object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
422     }
423
424     TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format, 
425                            debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
426     *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
427
428     return D3D_OK;
429 }
430
431 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
432
433     IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
434     IWineD3DStateBlockImpl *object;
435     int i,j;
436
437     D3DCREATEOBJECTINSTANCE(object, StateBlock)
438     object->blockType     = Type;
439
440     /* Special case - Used during initialization to produce a placeholder stateblock
441           so other functions called can update a state block                         */
442     if (Type == WINED3DSBT_INIT) {
443         /* Don't bother increasing the reference count otherwise a device will never
444            be freed due to circular dependencies                                   */
445         return D3D_OK;
446     }
447
448     /* Otherwise, might as well set the whole state block to the appropriate values */
449     IWineD3DDevice_AddRef(iface);
450     /* Otherwise, might as well set the whole state block to the appropriate values  */
451     if ( This->stateBlock != NULL) {
452        memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
453     } else {
454        memset(object->streamFreq, 1, sizeof(object->streamFreq));
455     }
456
457     /* Reset the ref and type after kludging it */
458     object->wineD3DDevice = This;
459     object->ref           = 1;
460     object->blockType     = Type;
461
462     TRACE("Updating changed flags appropriate for type %d\n", Type);
463
464     if (Type == WINED3DSBT_ALL) {
465         TRACE("ALL => Pretend everything has changed\n");
466         memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
467     } else if (Type == WINED3DSBT_PIXELSTATE) {
468
469         memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
470         /* TODO: Pixel Shader Constants */
471         object->changed.pixelShader = TRUE;
472         for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
473             object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
474         }
475         for (j = 0; j < GL_LIMITS(textures); i++) {
476             for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
477                 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
478             }
479         }
480         /* Setting sampler block changes states */
481         for (j = 0 ; j < GL_LIMITS(samplers); j++) {
482             for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
483
484                 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
485             }
486         }
487     } else if (Type == WINED3DSBT_VERTEXSTATE) {
488
489         memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
490
491         /* TODO: Vertex Shader Constants */
492         object->changed.vertexShader = TRUE;
493         for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
494             object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
495         }
496         for (j = 0; j < GL_LIMITS(textures); i++) {
497             for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
498                 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
499             }
500         }
501         /* Setting sampler block changes states */
502         for (j = 0 ; j < GL_LIMITS(samplers); j++) {
503             for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
504                 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
505             }
506         }
507
508     /* Duplicate light chain */
509     {
510         PLIGHTINFOEL *src = NULL;
511         PLIGHTINFOEL *dst = NULL;
512         PLIGHTINFOEL *newEl = NULL;
513         src = This->stateBlock->lights;
514         object->lights = NULL;
515
516
517         while (src) {
518             newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
519             if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
520             memcpy(newEl, src, sizeof(PLIGHTINFOEL));
521             newEl->prev = dst;
522             newEl->changed = TRUE;
523             newEl->enabledChanged = TRUE;
524             if (dst == NULL) {
525                 object->lights = newEl;
526             } else {
527                 dst->next = newEl;
528             }
529             dst = newEl;
530             src = src->next;
531         }
532
533      }
534
535     } else {
536         FIXME("Unrecognized state block type %d\n", Type);
537     }
538
539     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
540     return D3D_OK;
541 }
542
543
544 /* ************************************
545 MSDN:
546 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
547
548 Discard
549  [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. 
550
551 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.
552
553 ******************************** */
554  
555 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) {
556     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;    
557     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
558     unsigned int pow2Width, pow2Height;
559     unsigned int Size       = 1;
560     TRACE("(%p) Create surface\n",This);
561     
562     /** FIXME: Check ranges on the inputs are valid 
563      * MSDN
564      *   MultisampleQuality
565      *    [in] Quality level. The valid range is between zero and one less than the level
566      *    returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. 
567      *    Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
568      *    values of paired render targets, depth stencil surfaces, and the MultiSample type
569      *    must all match.
570       *******************************/
571
572
573     /**
574     * TODO: Discard MSDN
575     * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
576     *
577     * If this flag is set, the contents of the depth stencil buffer will be
578     * invalid after calling either IDirect3DDevice9::Present or  * IDirect3DDevice9::SetDepthStencilSurface
579     * with a different depth surface.
580     *
581     *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
582     ***************************/
583
584     if(MultisampleQuality < 0) {
585         FIXME("Invalid multisample level %ld \n", MultisampleQuality);
586         return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
587     }
588
589     if(MultisampleQuality > 0) {
590         FIXME("MultisampleQuality set to %ld, substituting 0  \n" , MultisampleQuality);
591         MultisampleQuality=0;
592     }
593
594     /** FIXME: Check that the format is supported
595     *    by the device.
596       *******************************/
597     /* TODO: add support for dxt2 and dxt4 formats */
598     if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT4) return D3DERR_NOTAVAILABLE;
599
600     /* Non-power2 support */
601
602     /* Find the nearest pow2 match */
603     pow2Width = pow2Height = 1;
604     while (pow2Width < Width) pow2Width <<= 1;
605     while (pow2Height < Height) pow2Height <<= 1;
606
607     if (pow2Width > Width || pow2Height > Height) {
608          /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
609         if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
610                || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
611             FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
612                     This, Width, Height);
613             return D3DERR_NOTAVAILABLE;
614         }
615     }
616
617     /** Check against the maximum texture sizes supported by the video card **/
618     if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
619         /* one of three options
620         1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
621         2: Set the texture to the maxium size (bad idea)
622         3:    WARN and return D3DERR_NOTAVAILABLE;
623         */
624         WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This, Width, Height, GL_LIMITS(texture_size));
625          return D3DERR_NOTAVAILABLE;
626     }
627
628
629
630     /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
631      *  it is based around 4x4 pixel blocks it requires padding, so allocate enough
632      *  space!
633       *********************************/
634     if (Format == WINED3DFMT_DXT1) {
635         /* DXT1 is half byte per pixel */
636        Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4)) >> 1;
637
638     } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
639                Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
640        Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4));
641     } else {
642        Size = (Width     * D3DFmtGetBpp(This, Format)) * Height;
643     }
644
645     /** Create the and initilise surface resource **/
646     D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
647     object->container = (IUnknown*) This;
648
649     object->currentDesc.Width      = Width;
650     object->currentDesc.Height     = Height;
651     object->currentDesc.MultiSampleType    = MultiSample;
652     object->currentDesc.MultiSampleQuality = MultisampleQuality;
653
654 /* Setup some glformat defaults */
655     object->glDescription.glFormat         = D3DFmt2GLFmt(This, object->resource.format);
656     object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
657     object->glDescription.glType           = D3DFmt2GLType(This, object->resource.format);
658     object->glDescription.textureName      = 0;
659     object->glDescription.level            = Level;
660     object->glDescription.target           = GL_TEXTURE_2D;
661
662     /* Internal data */
663     object->pow2Width  = pow2Width;
664     object->pow2Height = pow2Height;
665     object->nonpow2    = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
666     object->discard    = Discard;
667     object->activeLock = FALSE;
668     object->bytesPerPixel = D3DFmtGetBpp(This, Format);
669     object->pow2Size      = (pow2Width * object->bytesPerPixel) * pow2Height;
670
671     /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
672
673     /* Precalculated scaling for 'faked' non power of two texture coords */
674     object->pow2scalingFactorX  =  (((float)Width)  / ((float)pow2Width));
675     object->pow2scalingFactorY  =  (((float)Height) / ((float)pow2Height));
676     TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
677
678     TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
679
680     /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
681     * this function is too deap to need to care about things like this.
682     * Levels need to be checked too, and possibly Type wince they all affect what can be done.
683     * ****************************************/
684     switch(Pool) {
685     case D3DPOOL_SCRATCH:
686         if(Lockable == FALSE)
687             FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
688                 which are mutually exclusive, setting lockable to true\n");
689                 Lockable = TRUE;
690     break;
691     case D3DPOOL_SYSTEMMEM:
692         if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
693                                     this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
694     case D3DPOOL_MANAGED:
695         if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
696                                              Usage of DYNAMIC which are mutually exclusive, not doing \
697                                              anything just telling you.\n");
698     break;
699     case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
700         if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
701            && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
702             FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
703     break;
704     default:
705         FIXME("(%p) Unknown pool %d\n", This, Pool);
706     break;
707     };
708
709     if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
710         FIXME("Trying to create a render target that isn't in the default pool\n");
711     }
712
713
714     object->locked   = FALSE;
715     object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
716
717     /* mark the texture as dirty so that it get's loaded first time around*/
718     IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
719     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
720            This, Width, Height, Format, debug_d3dformat(Format),
721            (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
722     return D3D_OK;
723
724 }
725
726 HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
727                                                  DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
728                                                  IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
729                                                  D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
730
731     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
732     IWineD3DTextureImpl *object;
733     unsigned int i;
734     UINT tmpW;
735     UINT tmpH;
736     HRESULT hr;
737
738     TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
739
740     D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
741     D3DINITILIZEBASETEXTURE(object->baseTexture);    
742     object->width  = Width;
743     object->height = Height;
744     
745     /* Calculate levels for mip mapping */
746     if (Levels == 0) {
747         TRACE("calculating levels %d\n", object->baseTexture.levels);
748         object->baseTexture.levels++;
749         tmpW = Width;
750         tmpH = Height;
751         while (tmpW > 1 && tmpH > 1) {
752             tmpW = max(1, tmpW >> 1);
753             tmpH = max(1, tmpH >> 1);
754             object->baseTexture.levels++;
755         }
756         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
757     }
758
759     /* Generate all the surfaces */
760     tmpW = Width;
761     tmpH = Height;
762     for (i = 0; i < object->baseTexture.levels; i++)
763     {
764         /* use the callback to create the texture surface */
765         hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
766         if(hr!= D3D_OK) {
767             int j;
768             FIXME("Failed to create surface  %p \n",object);
769             /* clean up */
770             for(j = 0 ; j < i ; j++) {
771                 IWineD3DSurface_Release(object->surfaces[j]);
772             }
773             /* heap free object */
774             HeapFree(GetProcessHeap(),0,object);
775
776             *ppTexture = NULL;
777             return hr;
778         }
779
780         IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
781         TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
782         /* calculate the next mipmap level */
783         tmpW = max(1, tmpW >> 1);
784         tmpH = max(1, tmpH >> 1);
785     }
786
787     TRACE("(%p) : Created  texture %p\n", This, object);
788     return D3D_OK;
789 }
790
791 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
792                                                       UINT Width, UINT Height, UINT Depth,
793                                                       UINT Levels, DWORD Usage,
794                                                       WINED3DFORMAT Format, D3DPOOL Pool,
795                                                       IWineD3DVolumeTexture** ppVolumeTexture,
796                                                       HANDLE* pSharedHandle, IUnknown *parent,
797                                                       D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
798
799     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
800     IWineD3DVolumeTextureImpl *object;
801     unsigned int               i;
802     UINT                       tmpW;
803     UINT                       tmpH;
804     UINT                       tmpD;
805
806     D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
807     D3DINITILIZEBASETEXTURE(object->baseTexture);
808
809     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
810           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
811
812     object->width  = Width;
813     object->height = Height;
814     object->depth  = Depth;
815
816     /* Calculate levels for mip mapping */
817     if (Levels == 0) {
818         object->baseTexture.levels++;
819         tmpW = Width;
820         tmpH = Height;
821         tmpD = Depth;
822         while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
823             tmpW = max(1, tmpW >> 1);
824             tmpH = max(1, tmpH >> 1);
825             tmpD = max(1, tmpD >> 1);
826             object->baseTexture.levels++;
827         }
828         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
829     }
830
831     /* Generate all the surfaces */
832     tmpW = Width;
833     tmpH = Height;
834     tmpD = Depth;
835
836     for (i = 0; i < object->baseTexture.levels; i++)
837     {
838         /* Create the volume */
839         D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
840                            (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
841         IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
842
843         tmpW = max(1, tmpW >> 1);
844         tmpH = max(1, tmpH >> 1);
845         tmpD = max(1, tmpD >> 1);
846     }
847
848     *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
849     TRACE("(%p) : Created volume texture %p\n", This, object);
850     return D3D_OK;
851 }
852
853 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
854                                                UINT Width, UINT Height, UINT Depth,
855                                                DWORD Usage,
856                                                WINED3DFORMAT Format, D3DPOOL Pool,
857                                                IWineD3DVolume** ppVolume,
858                                                HANDLE* pSharedHandle, IUnknown *parent) {
859
860     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
861     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
862
863     D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
864
865     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
866           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
867
868     object->currentDesc.Width   = Width;
869     object->currentDesc.Height  = Height;
870     object->currentDesc.Depth   = Depth;
871     object->bytesPerPixel       = D3DFmtGetBpp(This, Format);
872
873     /** Note: Volume textures cannot be dxtn, hence no need to check here **/
874     object->lockable            = TRUE;
875     object->locked              = FALSE;
876     memset(&object->lockedBox, 0, sizeof(D3DBOX));
877     object->dirty = FALSE;
878     return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
879 }
880
881 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
882                                                     UINT Levels, DWORD Usage,
883                                                     WINED3DFORMAT Format, D3DPOOL Pool,
884                                                     IWineD3DCubeTexture** ppCubeTexture,
885                                                     HANDLE* pSharedHandle, IUnknown *parent,
886                                                     D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
887
888    IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
889    IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
890    unsigned int             i,j;
891    UINT                     tmpW;
892    HRESULT                  hr;
893
894    D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
895    D3DINITILIZEBASETEXTURE(object->baseTexture);
896
897    TRACE("(%p) Create Cube Texture \n", This);
898
899    object->edgeLength           = EdgeLength;
900
901    /* Calculate levels for mip mapping */
902    if (Levels == 0) {
903        object->baseTexture.levels++;
904        tmpW = EdgeLength;
905        while (tmpW > 1) {
906            tmpW = max(1, tmpW / 2);
907            object->baseTexture.levels++;
908        }
909        TRACE("Calculated levels = %d\n", object->baseTexture.levels);
910    }
911
912     /* Generate all the surfaces */
913     tmpW = EdgeLength;
914     for (i = 0; i < object->baseTexture.levels; i++) {
915
916         /* Create the 6 faces */
917         for (j = 0; j < 6; j++) {
918
919             hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
920                                    i /* Level */, &object->surfaces[j][i],pSharedHandle);
921
922             if(hr!= D3D_OK) {
923                 /* clean up */
924                 int k;
925                 int l;
926                 for (l=0;l<j;l++) {
927                     IWineD3DSurface_Release(object->surfaces[j][i]);
928                 }
929                 for (k=0;k<i;k++) {
930                     for (l=0;l<6;l++) {
931                     IWineD3DSurface_Release(object->surfaces[l][j]);
932                     }
933                 }
934
935                 FIXME("(%p) Failed to create surface\n",object);
936                 HeapFree(GetProcessHeap(),0,object);
937                 *ppCubeTexture = NULL;
938                 return hr;
939             }
940             IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
941             TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
942         }
943         tmpW = max(1, tmpW >> 1);
944     }
945
946     TRACE("(%p) : Created Cube Texture %p\n", This, object);
947     *ppCubeTexture = (IWineD3DCubeTexture *) object;
948     return D3D_OK;
949 }
950
951 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
952     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
953     IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
954
955     if(NULL == ppQuery) {
956         /* Just a check to see if we support this type of query */
957         HRESULT hr = D3DERR_NOTAVAILABLE;
958         /* Lie and say everything is good (we can return ok fake data from a stub) */
959         switch(Type) {
960         case WINED3DQUERYTYPE_VCACHE:
961         case WINED3DQUERYTYPE_RESOURCEMANAGER:
962         case WINED3DQUERYTYPE_VERTEXSTATS:
963         case WINED3DQUERYTYPE_EVENT:
964         case WINED3DQUERYTYPE_OCCLUSION:
965         case WINED3DQUERYTYPE_TIMESTAMP:
966         case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
967         case WINED3DQUERYTYPE_TIMESTAMPFREQ:
968         case WINED3DQUERYTYPE_PIPELINETIMINGS:
969         case WINED3DQUERYTYPE_INTERFACETIMINGS:
970         case WINED3DQUERYTYPE_VERTEXTIMINGS:
971         case WINED3DQUERYTYPE_PIXELTIMINGS:
972         case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
973         case WINED3DQUERYTYPE_CACHEUTILIZATION:
974             hr = D3D_OK;
975         break;
976         default:
977             FIXME("(%p) Unhandled query type %d\n",This , Type);
978         }
979         FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
980         return hr;
981     }
982
983     D3DCREATEOBJECTINSTANCE(object, Query)
984     object->type         = Type;
985     object->extendedData = 0;
986     TRACE("(%p) : Created Query %p\n", This, object);
987     return D3D_OK;
988 }
989
990 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
991 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS*  pPresentationParameters,                                                                   IWineD3DSwapChain** ppSwapChain,
992                                                             IUnknown* parent,
993                                                             D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
994                                                             D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
995     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
996
997     HDC                     hDc;
998     IWineD3DSwapChainImpl  *object; /** NOTE: impl ref allowed since this is a create function **/
999     int                     num;
1000     XVisualInfo             template;
1001     GLXContext              oldContext;
1002     Drawable                oldDrawable;
1003     HRESULT                 hr = D3D_OK;
1004
1005     TRACE("(%p) : Created Aditional Swap Chain\n", This);
1006
1007    /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1008    * does a device hold a reference to a swap chain giving them a lifetime of the device
1009    * or does the swap chain notify the device of it'd destruction.
1010     *******************************/
1011
1012     D3DCREATEOBJECTINSTANCE(object, SwapChain)
1013
1014     /* Initialize other useful values */
1015     object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1016
1017     /*********************
1018     * Lookup the window Handle and the relating X window handle
1019     ********************/
1020
1021     /* Setup hwnd we are using, plus which display this equates to */
1022     object->win_handle = *(pPresentationParameters->hDeviceWindow);
1023     if (!object->win_handle) {
1024         object->win_handle = This->createParms.hFocusWindow;
1025     }
1026
1027     object->win        = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1028     hDc                = GetDC(object->win_handle);
1029     object->display    = get_display(hDc);
1030     ReleaseDC(object->win_handle, hDc);
1031     TRACE("Using a display of %p %p  \n", object->display, hDc);
1032
1033     if (NULL == object->display || NULL == hDc) {
1034         WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1035         return D3DERR_NOTAVAILABLE;
1036     }
1037
1038     if (object->win == 0) {
1039         WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1040         return D3DERR_NOTAVAILABLE;
1041     }
1042     /**
1043     * Create an opengl context for the display visual
1044     *  NOTE: the visual is chosen as the window is created and the glcontext cannot
1045     *     use different properties after that point in time. FIXME: How to handle when requested format
1046     *     doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1047     *     it chooses is identical to the one already being used!
1048      **********************************/
1049
1050     /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1051     ENTER_GL();
1052
1053     /* Create a new context for this swapchain */
1054     template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1055     /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1056     (or the best possible if none is requested) */
1057     TRACE("Found x visual ID  : %ld\n", template.visualid);
1058
1059     object->visInfo   = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1060     if (NULL == object->visInfo) {
1061         ERR("cannot really get XVisual\n");
1062         LEAVE_GL();
1063         return D3DERR_NOTAVAILABLE;
1064     } else {
1065         int n, value;
1066         /* Write out some debug info about the visual/s */
1067         TRACE("Using x visual ID  : %ld\n", template.visualid);
1068         TRACE("        visual info: %p\n", object->visInfo);
1069         TRACE("        num items  : %d\n", num);
1070         for(n = 0;n < num; n++) {
1071             TRACE("=====item=====: %d\n", n + 1);
1072             TRACE("   visualid      : %ld\n", object->visInfo[n].visualid);
1073             TRACE("   screen        : %d\n",  object->visInfo[n].screen);
1074             TRACE("   depth         : %u\n",  object->visInfo[n].depth);
1075             TRACE("   class         : %d\n",  object->visInfo[n].class);
1076             TRACE("   red_mask      : %ld\n", object->visInfo[n].red_mask);
1077             TRACE("   green_mask    : %ld\n", object->visInfo[n].green_mask);
1078             TRACE("   blue_mask     : %ld\n", object->visInfo[n].blue_mask);
1079             TRACE("   colormap_size : %d\n",  object->visInfo[n].colormap_size);
1080             TRACE("   bits_per_rgb  : %d\n",  object->visInfo[n].bits_per_rgb);
1081             /* log some extra glx info */
1082             glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1083             TRACE("   gl_aux_buffers  : %d\n",  value);
1084             glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1085             TRACE("   gl_buffer_size  : %d\n",  value);
1086             glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1087             TRACE("   gl_red_size  : %d\n",  value);
1088             glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1089             TRACE("   gl_green_size  : %d\n",  value);
1090             glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1091             TRACE("   gl_blue_size  : %d\n",  value);
1092             glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1093             TRACE("   gl_alpha_size  : %d\n",  value);
1094             glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1095             TRACE("   gl_depth_size  : %d\n",  value);
1096             glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1097             TRACE("   gl_stencil_size : %d\n",  value);
1098         }
1099         /* Now choose a simila visual ID*/
1100     }
1101 #ifdef USE_CONTEXT_MANAGER
1102
1103     /** TODO: use a context mamager **/
1104 #endif
1105
1106     {
1107         IWineD3DSwapChain *implSwapChain;
1108         if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1109             /* The first time around we create the context that is shared with all other swapchains and render targets */
1110             object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1111             TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1112         } else {
1113
1114             TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1115             /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1116             /* and create a new context with the implicit swapchains context as the shared context */
1117             object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1118             IWineD3DSwapChain_Release(implSwapChain);
1119         }
1120     }
1121
1122     /* Cleanup */
1123     XFree(object->visInfo);
1124     object->visInfo = NULL;
1125
1126     if (NULL == object->glCtx) {
1127         ERR("cannot create glxContext\n");
1128         LEAVE_GL();
1129         return D3DERR_NOTAVAILABLE;
1130     }
1131
1132     LEAVE_GL();
1133     if (object->glCtx == NULL) {
1134         ERR("Error in context creation !\n");
1135         return D3DERR_INVALIDCALL;
1136     } else {
1137         TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1138                 object->win_handle, object->glCtx, object->win, object->visInfo);
1139     }
1140
1141    /*********************
1142    * Windowed / Fullscreen
1143    *******************/
1144
1145    /**
1146    * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1147    * so we should really check to see if their is a fullscreen swapchain already
1148    * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1149     **************************************/
1150
1151    if (!*(pPresentationParameters->Windowed)) {
1152
1153         DEVMODEW devmode;
1154         HDC      hdc;
1155         int      bpp = 0;
1156
1157         /* Get info on the current display setup */
1158         hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1159         bpp = GetDeviceCaps(hdc, BITSPIXEL);
1160         DeleteDC(hdc);
1161
1162         /* Change the display settings */
1163         memset(&devmode, 0, sizeof(DEVMODEW));
1164         devmode.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1165         devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1166         devmode.dmPelsWidth  = *(pPresentationParameters->BackBufferWidth);
1167         devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1168         MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1169         ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1170
1171         /* Make popup window */
1172         SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1173         SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1174                      *(pPresentationParameters->BackBufferWidth),
1175                      *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1176
1177
1178     }
1179
1180
1181     /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1182      *  then the corresponding dimension of the client area of the hDeviceWindow
1183      *  (or the focus window, if hDeviceWindow is NULL) is taken.
1184       **********************/
1185
1186     if (*(pPresentationParameters->Windowed) &&
1187         ((*(pPresentationParameters->BackBufferWidth)  == 0) ||
1188          (*(pPresentationParameters->BackBufferHeight) == 0))) {
1189
1190         RECT Rect;
1191         GetClientRect(object->win_handle, &Rect);
1192
1193         if (*(pPresentationParameters->BackBufferWidth) == 0) {
1194            *(pPresentationParameters->BackBufferWidth) = Rect.right;
1195            TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1196         }
1197         if (*(pPresentationParameters->BackBufferHeight) == 0) {
1198            *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1199            TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1200         }
1201     }
1202
1203    /*********************
1204    * finish off parameter initialization
1205    *******************/
1206
1207     /* Put the correct figures in the presentation parameters */
1208     TRACE("Coppying accross presentaion paraneters\n");
1209     object->presentParms.BackBufferWidth                = *(pPresentationParameters->BackBufferWidth);
1210     object->presentParms.BackBufferHeight               = *(pPresentationParameters->BackBufferHeight);
1211     object->presentParms.BackBufferFormat               = *(pPresentationParameters->BackBufferFormat);
1212     object->presentParms.BackBufferCount                = *(pPresentationParameters->BackBufferCount);
1213     object->presentParms.MultiSampleType                = *(pPresentationParameters->MultiSampleType);
1214     object->presentParms.MultiSampleQuality             = *(pPresentationParameters->MultiSampleQuality);
1215     object->presentParms.SwapEffect                     = *(pPresentationParameters->SwapEffect);
1216     object->presentParms.hDeviceWindow                  = *(pPresentationParameters->hDeviceWindow);
1217     object->presentParms.Windowed                       = *(pPresentationParameters->Windowed);
1218     object->presentParms.EnableAutoDepthStencil         = *(pPresentationParameters->EnableAutoDepthStencil);
1219     object->presentParms.AutoDepthStencilFormat         = *(pPresentationParameters->AutoDepthStencilFormat);
1220     object->presentParms.Flags                          = *(pPresentationParameters->Flags);
1221     object->presentParms.FullScreen_RefreshRateInHz     = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1222     object->presentParms.PresentationInterval           = *(pPresentationParameters->PresentationInterval);
1223
1224
1225    /*********************
1226    * Create the back, front and stencil buffers
1227    *******************/
1228     TRACE("calling rendertarget CB\n");
1229     hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1230                              object->presentParms.BackBufferWidth,
1231                              object->presentParms.BackBufferHeight,
1232                              object->presentParms.BackBufferFormat,
1233                              object->presentParms.MultiSampleType,
1234                              object->presentParms.MultiSampleQuality,
1235                              TRUE /* Lockable */,
1236                              &object->frontBuffer,
1237                              NULL /* pShared (always null)*/);
1238     if (object->frontBuffer != NULL)
1239         IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1240     TRACE("calling rendertarget CB\n");
1241     hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1242                              object->presentParms.BackBufferWidth,
1243                              object->presentParms.BackBufferHeight,
1244                              object->presentParms.BackBufferFormat,
1245                              object->presentParms.MultiSampleType,
1246                              object->presentParms.MultiSampleQuality,
1247                              TRUE /* Lockable */,
1248                              &object->backBuffer,
1249                              NULL /* pShared (always null)*/);
1250     if (object->backBuffer != NULL)
1251        IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1252
1253     /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1254     if (pPresentationParameters->EnableAutoDepthStencil) {
1255         TRACE("Creating depth stencil buffer\n");
1256         if (This->depthStencilBuffer == NULL ) {
1257             hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1258                                     object->presentParms.BackBufferWidth,
1259                                     object->presentParms.BackBufferHeight,
1260                                     object->presentParms.AutoDepthStencilFormat,
1261                                     object->presentParms.MultiSampleType,
1262                                     object->presentParms.MultiSampleQuality,
1263                                     FALSE /* FIXME: Discard */,
1264                                     &This->depthStencilBuffer,
1265                                     NULL /* pShared (always null)*/  );
1266             if (This->depthStencilBuffer != NULL)
1267                 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1268         }
1269
1270         /** TODO: A check on width, height and multisample types
1271         *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1272          ****************************/
1273         object->wantsDepthStencilBuffer = TRUE;
1274     } else {
1275         object->wantsDepthStencilBuffer = FALSE;
1276     }
1277
1278     TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1279
1280
1281    /*********************
1282    * init the default renderTarget management
1283    *******************/
1284     object->drawable     = object->win;
1285     object->render_ctx   = object->glCtx;
1286
1287     if(hr == D3D_OK) {
1288         /*********************
1289          * Setup some defaults and clear down the buffers
1290          *******************/
1291         ENTER_GL();
1292         /** save current context and drawable **/
1293         oldContext   =   glXGetCurrentContext();
1294         oldDrawable  =   glXGetCurrentDrawable();
1295
1296         TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1297         if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1298             ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1299         }
1300         checkGLcall("glXMakeCurrent");
1301
1302         TRACE("Setting up the screen\n");
1303         /* Clear the screen */
1304         glClearColor(0.0, 0.0, 0.0, 0.0);
1305         checkGLcall("glClearColor");
1306         glClearIndex(0);
1307         glClearDepth(1);
1308         glClearStencil(0xffff);
1309
1310         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1311         checkGLcall("glClear");
1312
1313         glColor3f(1.0, 1.0, 1.0);
1314         checkGLcall("glColor3f");
1315
1316         glEnable(GL_LIGHTING);
1317         checkGLcall("glEnable");
1318
1319         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1320         checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1321
1322         glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1323         checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1324
1325         glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1326         checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1327
1328         /* switch back to the original context (unless it was zero)*/
1329         if (This->swapchains != NULL) {
1330             /** TODO: restore the context and drawable **/
1331             glXMakeCurrent(object->display, oldDrawable, oldContext);
1332         }
1333
1334         LEAVE_GL();
1335
1336         { /* Finally add the swapchain to the end of the devices' swapchain list */
1337             SwapChainList **nextSwapchain;
1338             nextSwapchain = &This->swapchains;
1339             while(*nextSwapchain != NULL) {
1340                 nextSwapchain = &((*nextSwapchain)->next);
1341             }
1342             (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1343             (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1344         }
1345         TRACE("Set swapchain to %p\n", object);
1346     } else { /* something went wrong so clean up */
1347         IUnknown* bufferParent;
1348         if (object->frontBuffer) {
1349             IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1350             IUnknown_Release(bufferParent); /* once for the get parent */
1351             if(IUnknown_Release(bufferParent) > 0) {
1352                 FIXME("(%p) Something's still holding the front buffer\n",This);
1353             }
1354         }
1355         if (object->backBuffer) {
1356             IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1357             IUnknown_Release(bufferParent); /* once for the get parent */
1358             if(IUnknown_Release(bufferParent) > 0) {
1359                 FIXME("(%p) Something's still holding the back buffer\n",This);
1360             }
1361         }
1362         /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1363         /* Clean up the context */
1364         /* check that we are the current context first (we shouldn't be though!) */
1365         if (object->glCtx != 0) {
1366             if(glXGetCurrentContext() == object->glCtx) {
1367                 glXMakeCurrent(object->display, None, NULL);
1368             }
1369             glXDestroyContext(object->display, object->glCtx);
1370         }
1371         HeapFree(GetProcessHeap(), 0, object);
1372
1373     }
1374     return hr;
1375 }
1376
1377 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1378 UINT     WINAPI  IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1379     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1380     unsigned int numberOfSwapChains = 0;
1381     SwapChainList          *swapchain;
1382
1383     swapchain = This->swapchains;
1384     /* itterate through the list to get a count */
1385     while (swapchain != NULL) {
1386         swapchain = swapchain->next;
1387         numberOfSwapChains++;
1388     }
1389
1390     TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1391     return numberOfSwapChains;
1392 }
1393
1394 HRESULT  WINAPI  IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1395     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1396     SwapChainList *swapchain;
1397     HRESULT hr = D3DERR_INVALIDCALL;
1398     swapchain = This->swapchains;
1399     TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1400
1401
1402     TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1403     while (iSwapChain > 0 && swapchain != NULL) {
1404         swapchain = swapchain->next;
1405         iSwapChain--;
1406     }
1407
1408     if (iSwapChain > 0 || swapchain == NULL) {
1409         FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1410         *pSwapChain = NULL;
1411     } else {
1412         /** TODO: move off to a linkesList implementation **/
1413         *pSwapChain = swapchain->swapchain;
1414         IWineD3DSwapChain_AddRef(*pSwapChain);
1415         hr = D3D_OK;
1416     }
1417
1418     TRACE("(%p) returning %p\n", This, *pSwapChain);
1419     return hr;
1420 }
1421
1422 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS*  pPresentationParameters) {
1423     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1424
1425     FIXME("(%p) : Stub\n",This);
1426     return D3D_OK;
1427
1428 }
1429
1430 /*****
1431  * Vertex Declaration
1432  *****/
1433 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1434     IWineD3DDeviceImpl            *This   = (IWineD3DDeviceImpl *)iface;
1435     IWineD3DVertexDeclarationImpl *object = NULL;
1436     HRESULT hr = D3D_OK;
1437     TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1438     D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1439     object->allFVF = 0;
1440
1441     hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1442
1443     return hr;
1444 }
1445
1446 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1447 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface,  CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1448     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
1449     IWineD3DVertexShaderImpl *object;  /* NOTE: impl usage is ok, this is a create */
1450     D3DCREATEOBJECTINSTANCE(object, VertexShader)
1451     object->function      = pFunction;
1452     FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1453     return D3D_OK;
1454
1455 }
1456
1457 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1458     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1459     FIXME("(%p) : Stub\n", This);
1460     return D3D_OK;
1461 }
1462
1463 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1464    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1465    *ppD3D= This->wineD3D;
1466    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
1467    IWineD3D_AddRef(*ppD3D);
1468    return D3D_OK;
1469
1470 }
1471
1472 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1473     /** NOTE: There's a probably  a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1474     * Into the video ram as possible and seeing how many fit
1475     * you can also get the correct initial value from via X and ATI's driver
1476     *******************/
1477     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1478     static BOOL showfixmes = TRUE;
1479     if (showfixmes) {
1480         FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1481          ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1482          showfixmes = FALSE;
1483     }
1484     TRACE("(%p) :  emulating %dMib for now, returning %dMib\n",  This, (emulated_textureram/(1024*1024)),
1485          ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1486     /* videomemory is simulated videomemory + AGP memory left */
1487     return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1488 }
1489
1490
1491
1492 /*****
1493  * Get / Set FVF
1494  *****/
1495 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1496     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1497
1498     /* Update the current state block */
1499     This->updateStateBlock->fvf              = fvf;
1500     This->updateStateBlock->changed.fvf      = TRUE;
1501     This->updateStateBlock->set.fvf          = TRUE;
1502
1503     TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1504     /* clear down the vertex declaration
1505      NOTE: Axis and Allies doesn't work properly otherwise
1506      (may be a stateblock problem though!)
1507     */
1508     /* No difference if recording or not */
1509     return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1510
1511 }
1512
1513
1514 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1515     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1516     TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1517     *pfvf = This->stateBlock->fvf;
1518     return D3D_OK;
1519 }
1520
1521 /*****
1522  * Get / Set Stream Source
1523  *****/
1524 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1525     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
1526     IWineD3DVertexBuffer     *oldSrc;
1527
1528     oldSrc = This->stateBlock->streamSource[StreamNumber];
1529     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1530
1531     This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1532     This->updateStateBlock->set.streamSource[StreamNumber]     = TRUE;
1533     This->updateStateBlock->streamStride[StreamNumber]         = Stride;
1534     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
1535     This->updateStateBlock->streamOffset[StreamNumber]         = OffsetInBytes;
1536
1537     /* Handle recording of state blocks */
1538     if (This->isRecordingState) {
1539         TRACE("Recording... not performing anything\n");
1540         return D3D_OK;
1541     }
1542
1543     /* Not recording... */
1544     if (pStreamData != NULL) {
1545         IUnknown *newVertexBufferParent;
1546         /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1547         IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1548     }
1549     if (oldSrc != NULL) {
1550         IUnknown *oldVertexBufferParent;
1551         IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1552         IUnknown_Release(oldVertexBufferParent);
1553         IUnknown_Release(oldVertexBufferParent);
1554     }
1555
1556     return D3D_OK;
1557 }
1558
1559 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1560     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1561
1562     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1563     *pStream = This->stateBlock->streamSource[StreamNumber];
1564     *pStride = This->stateBlock->streamStride[StreamNumber];
1565     *pOffset = This->stateBlock->streamOffset[StreamNumber];
1566     if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1567     return D3D_OK;
1568 }
1569
1570 /*Should be quite easy, just an extension of vertexdata
1571 ref...
1572 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1573
1574 The divider is a bit odd though
1575
1576 VertexOffset = StartVertex / Divider * StreamStride +
1577                VertexIndex / Divider * StreamStride + StreamOffset
1578
1579 */
1580 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
1581     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1582
1583     FIXME("(%p) : stub\n", This);
1584     return D3D_OK;
1585 }
1586
1587 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
1588     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1589
1590     FIXME("(%p) : stub\n", This);
1591     return D3D_OK;
1592 }
1593
1594 /*****
1595  * Get / Set & Multiply Transform
1596  *****/
1597 HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1598     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1599
1600     /* Most of this routine, comments included copied from ddraw tree initially: */
1601     TRACE("(%p) : Transform State=%d\n", This, d3dts);
1602
1603     /* Handle recording of state blocks */
1604     if (This->isRecordingState) {
1605         TRACE("Recording... not performing anything\n");
1606         This->updateStateBlock->changed.transform[d3dts] = TRUE;
1607         This->updateStateBlock->set.transform[d3dts]     = TRUE;
1608         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1609         return D3D_OK;
1610     }
1611
1612     /*
1613      * If the new matrix is the same as the current one,
1614      * we cut off any further processing. this seems to be a reasonable
1615      * optimization because as was noticed, some apps (warcraft3 for example)
1616      * tend towards setting the same matrix repeatedly for some reason.
1617      *
1618      * From here on we assume that the new matrix is different, wherever it matters.
1619      */
1620     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1621         TRACE("The app is setting the same matrix over again\n");
1622         return D3D_OK;
1623     } else {
1624         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1625     }
1626
1627     /*
1628        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1629        where ViewMat = Camera space, WorldMat = world space.
1630
1631        In OpenGL, camera and world space is combined into GL_MODELVIEW
1632        matrix.  The Projection matrix stay projection matrix.
1633      */
1634
1635     /* Capture the times we can just ignore the change for now */
1636     if (d3dts == D3DTS_WORLDMATRIX(0)) {
1637         This->modelview_valid = FALSE;
1638         return D3D_OK;
1639
1640     } else if (d3dts == D3DTS_PROJECTION) {
1641         This->proj_valid = FALSE;
1642         return D3D_OK;
1643
1644     } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1645         /* Indexed Vertex Blending Matrices 256 -> 511  */
1646         /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1647         FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1648         return D3D_OK;
1649     }
1650
1651     /* Now we really are going to have to change a matrix */
1652     ENTER_GL();
1653
1654     if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1655         if (d3dts < GL_LIMITS(textures)) {
1656             int tex = d3dts - D3DTS_TEXTURE0;
1657             GLACTIVETEXTURE(tex);
1658             set_texture_matrix((float *)lpmatrix,
1659                                This->updateStateBlock->textureState[tex][WINED3DTSS_TEXTURETRANSFORMFLAGS], (This->stateBlock->textureState[tex][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
1660         }
1661
1662     } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1663         unsigned int k;
1664
1665         /* If we are changing the View matrix, reset the light and clipping planes to the new view
1666          * NOTE: We have to reset the positions even if the light/plane is not currently
1667          *       enabled, since the call to enable it will not reset the position.
1668          * NOTE2: Apparently texture transforms do NOT need reapplying
1669          */
1670
1671         PLIGHTINFOEL *lightChain = NULL;
1672         This->modelview_valid = FALSE;
1673         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1674
1675         glMatrixMode(GL_MODELVIEW);
1676         checkGLcall("glMatrixMode(GL_MODELVIEW)");
1677         glPushMatrix();
1678         glLoadMatrixf((float *)lpmatrix);
1679         checkGLcall("glLoadMatrixf(...)");
1680
1681         /* Reset lights */
1682         lightChain = This->stateBlock->lights;
1683         while (lightChain && lightChain->glIndex != -1) {
1684             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1685             checkGLcall("glLightfv posn");
1686             glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1687             checkGLcall("glLightfv dirn");
1688             lightChain = lightChain->next;
1689         }
1690
1691         /* Reset Clipping Planes if clipping is enabled */
1692         for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1693             glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1694             checkGLcall("glClipPlane");
1695         }
1696         glPopMatrix();
1697
1698     } else { /* What was requested!?? */
1699         WARN("invalid matrix specified: %i\n", d3dts);
1700     }
1701
1702     /* Release lock, all done */
1703     LEAVE_GL();
1704     return D3D_OK;
1705
1706 }
1707 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1708     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1709     TRACE("(%p) : for Transform State %d\n", This, State);
1710     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1711     return D3D_OK;
1712 }
1713
1714 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1715     D3DMATRIX *mat = NULL;
1716     D3DMATRIX temp;
1717
1718     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1719      * below means it will be recorded in a state block change, but it
1720      * works regardless where it is recorded.
1721      * If this is found to be wrong, change to StateBlock.
1722      */
1723     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1724     TRACE("(%p) : For state %u\n", This, State);
1725
1726     if (State < HIGHEST_TRANSFORMSTATE)
1727     {
1728         mat = &This->updateStateBlock->transforms[State];
1729     } else {
1730         FIXME("Unhandled transform state!!\n");
1731     }
1732
1733     /* Copied from ddraw code:  */
1734     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);
1735     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);
1736     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);
1737     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);
1738
1739     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);
1740     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);
1741     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);
1742     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);
1743
1744     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);
1745     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);
1746     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);
1747     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);
1748
1749     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);
1750     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);
1751     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);
1752     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);
1753
1754     /* Apply change via set transform - will reapply to eg. lights this way */
1755     IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1756     return D3D_OK;
1757 }
1758
1759 /*****
1760  * Get / Set Light
1761  *   WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1762  *****/
1763 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1764    you can reference any indexes you want as long as that number max are enabled at any
1765    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1766    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1767    but when recording, just build a chain pretty much of commands to be replayed.                  */
1768
1769 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1770     float rho;
1771     PLIGHTINFOEL *object, *temp;
1772
1773     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1774     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1775
1776     /* If recording state block, just add to end of lights chain */
1777     if (This->isRecordingState) {
1778         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1779         if (NULL == object) {
1780             return D3DERR_OUTOFVIDEOMEMORY;
1781         }
1782         memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1783         object->OriginalIndex = Index;
1784         object->glIndex = -1;
1785         object->changed = TRUE;
1786
1787         /* Add to the END of the chain of lights changes to be replayed */
1788         if (This->updateStateBlock->lights == NULL) {
1789             This->updateStateBlock->lights = object;
1790         } else {
1791             temp = This->updateStateBlock->lights;
1792             while (temp->next != NULL) temp=temp->next;
1793             temp->next = object;
1794         }
1795         TRACE("Recording... not performing anything more\n");
1796         return D3D_OK;
1797     }
1798
1799     /* Ok, not recording any longer so do real work */
1800     object = This->stateBlock->lights;
1801     while (object != NULL && object->OriginalIndex != Index) object = object->next;
1802
1803     /* If we didn't find it in the list of lights, time to add it */
1804     if (object == NULL) {
1805         PLIGHTINFOEL *insertAt,*prevPos;
1806
1807         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1808         if (NULL == object) {
1809             return D3DERR_OUTOFVIDEOMEMORY;
1810         }
1811         object->OriginalIndex = Index;
1812         object->glIndex = -1;
1813
1814         /* Add it to the front of list with the idea that lights will be changed as needed
1815            BUT after any lights currently assigned GL indexes                             */
1816         insertAt = This->stateBlock->lights;
1817         prevPos  = NULL;
1818         while (insertAt != NULL && insertAt->glIndex != -1) {
1819             prevPos  = insertAt;
1820             insertAt = insertAt->next;
1821         }
1822
1823         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1824             This->stateBlock->lights = object;
1825         } else if (insertAt == NULL) { /* End of list */
1826             prevPos->next = object;
1827             object->prev = prevPos;
1828         } else { /* Middle of chain */
1829             if (prevPos == NULL) {
1830                 This->stateBlock->lights = object;
1831             } else {
1832                 prevPos->next = object;
1833             }
1834             object->prev = prevPos;
1835             object->next = insertAt;
1836             insertAt->prev = object;
1837         }
1838     }
1839
1840     /* Initialze the object */
1841     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,
1842           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1843           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1844           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1845     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1846           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1847     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1848
1849     /* Save away the information */
1850     memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1851
1852     switch (pLight->Type) {
1853     case D3DLIGHT_POINT:
1854         /* Position */
1855         object->lightPosn[0] = pLight->Position.x;
1856         object->lightPosn[1] = pLight->Position.y;
1857         object->lightPosn[2] = pLight->Position.z;
1858         object->lightPosn[3] = 1.0f;
1859         object->cutoff = 180.0f;
1860         /* FIXME: Range */
1861         break;
1862
1863     case D3DLIGHT_DIRECTIONAL:
1864         /* Direction */
1865         object->lightPosn[0] = -pLight->Direction.x;
1866         object->lightPosn[1] = -pLight->Direction.y;
1867         object->lightPosn[2] = -pLight->Direction.z;
1868         object->lightPosn[3] = 0.0;
1869         object->exponent     = 0.0f;
1870         object->cutoff       = 180.0f;
1871         break;
1872
1873     case D3DLIGHT_SPOT:
1874         /* Position */
1875         object->lightPosn[0] = pLight->Position.x;
1876         object->lightPosn[1] = pLight->Position.y;
1877         object->lightPosn[2] = pLight->Position.z;
1878         object->lightPosn[3] = 1.0;
1879
1880         /* Direction */
1881         object->lightDirn[0] = pLight->Direction.x;
1882         object->lightDirn[1] = pLight->Direction.y;
1883         object->lightDirn[2] = pLight->Direction.z;
1884         object->lightDirn[3] = 1.0;
1885
1886         /*
1887          * opengl-ish and d3d-ish spot lights use too different models for the
1888          * light "intensity" as a function of the angle towards the main light direction,
1889          * so we only can approximate very roughly.
1890          * however spot lights are rather rarely used in games (if ever used at all).
1891          * furthermore if still used, probably nobody pays attention to such details.
1892          */
1893         if (pLight->Falloff == 0) {
1894             rho = 6.28f;
1895         } else {
1896             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1897         }
1898         if (rho < 0.0001) rho = 0.0001f;
1899         object->exponent = -0.3/log(cos(rho/2));
1900         object->cutoff = pLight->Phi*90/M_PI;
1901
1902         /* FIXME: Range */
1903         break;
1904
1905     default:
1906         FIXME("Unrecognized light type %d\n", pLight->Type);
1907     }
1908
1909     /* Update the live definitions if the light is currently assigned a glIndex */
1910     if (object->glIndex != -1) {
1911         setup_light(iface, object->glIndex, object);
1912     }
1913     return D3D_OK;
1914 }
1915
1916 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1917     PLIGHTINFOEL *lightInfo = NULL;
1918     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1919     TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1920
1921     /* Locate the light in the live lights */
1922     lightInfo = This->stateBlock->lights;
1923     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1924
1925     if (lightInfo == NULL) {
1926         TRACE("Light information requested but light not defined\n");
1927         return D3DERR_INVALIDCALL;
1928     }
1929
1930     memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1931     return D3D_OK;
1932 }
1933
1934 /*****
1935  * Get / Set Light Enable
1936  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1937  *****/
1938 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1939     PLIGHTINFOEL *lightInfo = NULL;
1940     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1941     TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1942
1943     /* If recording state block, just add to end of lights chain with changedEnable set to true */
1944     if (This->isRecordingState) {
1945         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1946         if (NULL == lightInfo) {
1947             return D3DERR_OUTOFVIDEOMEMORY;
1948         }
1949         lightInfo->OriginalIndex = Index;
1950         lightInfo->glIndex = -1;
1951         lightInfo->enabledChanged = TRUE;
1952
1953         /* Add to the END of the chain of lights changes to be replayed */
1954         if (This->updateStateBlock->lights == NULL) {
1955             This->updateStateBlock->lights = lightInfo;
1956         } else {
1957             PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1958             while (temp->next != NULL) temp=temp->next;
1959             temp->next = lightInfo;
1960         }
1961         TRACE("Recording... not performing anything more\n");
1962         return D3D_OK;
1963     }
1964
1965     /* Not recording... So, locate the light in the live lights */
1966     lightInfo = This->stateBlock->lights;
1967     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1968
1969     /* Special case - enabling an undefined light creates one with a strict set of parms! */
1970     if (lightInfo == NULL) {
1971         D3DLIGHT9 lightParms;
1972         /* Warning - untested code :-) Prob safe to change fixme to a trace but
1973              wait until someone confirms it seems to work!                     */
1974         TRACE("Light enabled requested but light not defined, so defining one!\n");
1975         lightParms.Type = D3DLIGHT_DIRECTIONAL;
1976         lightParms.Diffuse.r = 1.0;
1977         lightParms.Diffuse.g = 1.0;
1978         lightParms.Diffuse.b = 1.0;
1979         lightParms.Diffuse.a = 0.0;
1980         lightParms.Specular.r = 0.0;
1981         lightParms.Specular.g = 0.0;
1982         lightParms.Specular.b = 0.0;
1983         lightParms.Specular.a = 0.0;
1984         lightParms.Ambient.r = 0.0;
1985         lightParms.Ambient.g = 0.0;
1986         lightParms.Ambient.b = 0.0;
1987         lightParms.Ambient.a = 0.0;
1988         lightParms.Position.x = 0.0;
1989         lightParms.Position.y = 0.0;
1990         lightParms.Position.z = 0.0;
1991         lightParms.Direction.x = 0.0;
1992         lightParms.Direction.y = 0.0;
1993         lightParms.Direction.z = 1.0;
1994         lightParms.Range = 0.0;
1995         lightParms.Falloff = 0.0;
1996         lightParms.Attenuation0 = 0.0;
1997         lightParms.Attenuation1 = 0.0;
1998         lightParms.Attenuation2 = 0.0;
1999         lightParms.Theta = 0.0;
2000         lightParms.Phi = 0.0;
2001         IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2002
2003         /* Search for it again! Should be fairly quick as near head of list */
2004         lightInfo = This->stateBlock->lights;
2005         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2006         if (lightInfo == NULL) {
2007             FIXME("Adding default lights has failed dismally\n");
2008             return D3DERR_INVALIDCALL;
2009         }
2010     }
2011
2012     /* OK, we now have a light... */
2013     if (Enable == FALSE) {
2014
2015         /* If we are disabling it, check it was enabled, and
2016            still only do something if it has assigned a glIndex (which it should have!)   */
2017         if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2018             TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2019             ENTER_GL();
2020             glDisable(GL_LIGHT0 + lightInfo->glIndex);
2021             checkGLcall("glDisable GL_LIGHT0+Index");
2022             LEAVE_GL();
2023         } else {
2024             TRACE("Nothing to do as light was not enabled\n");
2025         }
2026         lightInfo->lightEnabled = FALSE;
2027     } else {
2028
2029         /* We are enabling it. If it is enabled, it's really simple */
2030         if (lightInfo->lightEnabled) {
2031             /* nop */
2032             TRACE("Nothing to do as light was enabled\n");
2033
2034         /* If it already has a glIndex, it's still simple */
2035         } else if (lightInfo->glIndex != -1) {
2036             TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2037             lightInfo->lightEnabled = TRUE;
2038             ENTER_GL();
2039             glEnable(GL_LIGHT0 + lightInfo->glIndex);
2040             checkGLcall("glEnable GL_LIGHT0+Index already setup");
2041             LEAVE_GL();
2042
2043         /* Otherwise got to find space - lights are ordered gl indexes first */
2044         } else {
2045             PLIGHTINFOEL *bsf  = NULL;
2046             PLIGHTINFOEL *pos  = This->stateBlock->lights;
2047             PLIGHTINFOEL *prev = NULL;
2048             int           Index= 0;
2049             int           glIndex = -1;
2050
2051             /* Try to minimize changes as much as possible */
2052             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2053
2054                 /* Try to remember which index can be replaced if necessary */
2055                 if (bsf==NULL && pos->lightEnabled == FALSE) {
2056                     /* Found a light we can replace, save as best replacement */
2057                     bsf = pos;
2058                 }
2059
2060                 /* Step to next space */
2061                 prev = pos;
2062                 pos = pos->next;
2063                 Index ++;
2064             }
2065
2066             /* If we have too many active lights, fail the call */
2067             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2068                 FIXME("Program requests too many concurrent lights\n");
2069                 return D3DERR_INVALIDCALL;
2070
2071             /* If we have allocated all lights, but not all are enabled,
2072                reuse one which is not enabled                           */
2073             } else if (Index == This->maxConcurrentLights) {
2074                 /* use bsf - Simply swap the new light and the BSF one */
2075                 PLIGHTINFOEL *bsfNext = bsf->next;
2076                 PLIGHTINFOEL *bsfPrev = bsf->prev;
2077
2078                 /* Sort out ends */
2079                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2080                 if (bsf->prev != NULL) {
2081                     bsf->prev->next = lightInfo;
2082                 } else {
2083                     This->stateBlock->lights = lightInfo;
2084                 }
2085
2086                 /* If not side by side, lots of chains to update */
2087                 if (bsf->next != lightInfo) {
2088                     lightInfo->prev->next = bsf;
2089                     bsf->next->prev = lightInfo;
2090                     bsf->next       = lightInfo->next;
2091                     bsf->prev       = lightInfo->prev;
2092                     lightInfo->next = bsfNext;
2093                     lightInfo->prev = bsfPrev;
2094
2095                 } else {
2096                     /* Simple swaps */
2097                     bsf->prev = lightInfo;
2098                     bsf->next = lightInfo->next;
2099                     lightInfo->next = bsf;
2100                     lightInfo->prev = bsfPrev;
2101                 }
2102
2103
2104                 /* Update states */
2105                 glIndex = bsf->glIndex;
2106                 bsf->glIndex = -1;
2107                 lightInfo->glIndex = glIndex;
2108                 lightInfo->lightEnabled = TRUE;
2109
2110                 /* Finally set up the light in gl itself */
2111                 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2112                 ENTER_GL();
2113                 setup_light(iface, glIndex, lightInfo);
2114                 glEnable(GL_LIGHT0 + glIndex);
2115                 checkGLcall("glEnable GL_LIGHT0 new setup");
2116                 LEAVE_GL();
2117
2118             /* If we reached the end of the allocated lights, with space in the
2119                gl lights, setup a new light                                     */
2120             } else if (pos->glIndex == -1) {
2121
2122                 /* We reached the end of the allocated gl lights, so already
2123                     know the index of the next one!                          */
2124                 glIndex = Index;
2125                 lightInfo->glIndex = glIndex;
2126                 lightInfo->lightEnabled = TRUE;
2127
2128                 /* In an ideal world, it's already in the right place */
2129                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2130                    /* No need to move it */
2131                 } else {
2132                     /* Remove this light from the list */
2133                     lightInfo->prev->next = lightInfo->next;
2134                     if (lightInfo->next != NULL) {
2135                         lightInfo->next->prev = lightInfo->prev;
2136                     }
2137
2138                     /* Add in at appropriate place (inbetween prev and pos) */
2139                     lightInfo->prev = prev;
2140                     lightInfo->next = pos;
2141                     if (prev == NULL) {
2142                         This->stateBlock->lights = lightInfo;
2143                     } else {
2144                         prev->next = lightInfo;
2145                     }
2146                     if (pos != NULL) {
2147                         pos->prev = lightInfo;
2148                     }
2149                 }
2150
2151                 /* Finally set up the light in gl itself */
2152                 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2153                 ENTER_GL();
2154                 setup_light(iface, glIndex, lightInfo);
2155                 glEnable(GL_LIGHT0 + glIndex);
2156                 checkGLcall("glEnable GL_LIGHT0 new setup");
2157                 LEAVE_GL();
2158
2159             }
2160         }
2161     }
2162     return D3D_OK;
2163 }
2164
2165 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2166
2167     PLIGHTINFOEL *lightInfo = NULL;
2168     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2169     TRACE("(%p) : for idx(%ld)\n", This, Index);
2170
2171     /* Locate the light in the live lights */
2172     lightInfo = This->stateBlock->lights;
2173     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2174
2175     if (lightInfo == NULL) {
2176         TRACE("Light enabled state requested but light not defined\n");
2177         return D3DERR_INVALIDCALL;
2178     }
2179     *pEnable = lightInfo->lightEnabled;
2180     return D3D_OK;
2181 }
2182
2183 /*****
2184  * Get / Set Clip Planes
2185  *****/
2186 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2187     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2188     TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2189
2190     /* Validate Index */
2191     if (Index >= GL_LIMITS(clipplanes)) {
2192         TRACE("Application has requested clipplane this device doesn't support\n");
2193         return D3DERR_INVALIDCALL;
2194     }
2195
2196     This->updateStateBlock->changed.clipplane[Index] = TRUE;
2197     This->updateStateBlock->set.clipplane[Index] = TRUE;
2198     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2199     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2200     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2201     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2202
2203     /* Handle recording of state blocks */
2204     if (This->isRecordingState) {
2205         TRACE("Recording... not performing anything\n");
2206         return D3D_OK;
2207     }
2208
2209     /* Apply it */
2210
2211     ENTER_GL();
2212
2213     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2214     glMatrixMode(GL_MODELVIEW);
2215     glPushMatrix();
2216     glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2217
2218     TRACE("Clipplane [%f,%f,%f,%f]\n",
2219           This->updateStateBlock->clipplane[Index][0],
2220           This->updateStateBlock->clipplane[Index][1],
2221           This->updateStateBlock->clipplane[Index][2],
2222           This->updateStateBlock->clipplane[Index][3]);
2223     glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2224     checkGLcall("glClipPlane");
2225
2226     glPopMatrix();
2227     LEAVE_GL();
2228
2229     return D3D_OK;
2230 }
2231
2232 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2233     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2234     TRACE("(%p) : for idx %ld\n", This, Index);
2235
2236     /* Validate Index */
2237     if (Index >= GL_LIMITS(clipplanes)) {
2238         TRACE("Application has requested clipplane this device doesn't support\n");
2239         return D3DERR_INVALIDCALL;
2240     }
2241
2242     pPlane[0] = This->stateBlock->clipplane[Index][0];
2243     pPlane[1] = This->stateBlock->clipplane[Index][1];
2244     pPlane[2] = This->stateBlock->clipplane[Index][2];
2245     pPlane[3] = This->stateBlock->clipplane[Index][3];
2246     return D3D_OK;
2247 }
2248
2249 /*****
2250  * Get / Set Clip Plane Status
2251  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2252  *****/
2253 HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2254     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2255     FIXME("(%p) : stub\n", This);
2256     if (NULL == pClipStatus) {
2257       return D3DERR_INVALIDCALL;
2258     }
2259     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2260     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2261     return D3D_OK;
2262 }
2263
2264 HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2265     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2266     FIXME("(%p) : stub\n", This);
2267     if (NULL == pClipStatus) {
2268       return D3DERR_INVALIDCALL;
2269     }
2270     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2271     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2272     return D3D_OK;
2273 }
2274
2275 /*****
2276  * Get / Set Material
2277  *   WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2278  *****/
2279 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2280     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2281
2282     This->updateStateBlock->changed.material = TRUE;
2283     This->updateStateBlock->set.material = TRUE;
2284     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2285
2286     /* Handle recording of state blocks */
2287     if (This->isRecordingState) {
2288         TRACE("Recording... not performing anything\n");
2289         return D3D_OK;
2290     }
2291
2292     ENTER_GL();
2293     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2294     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2295     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2296     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2297     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2298
2299     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2300     checkGLcall("glMaterialfv");
2301     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2302     checkGLcall("glMaterialfv");
2303
2304     /* Only change material color if specular is enabled, otherwise it is set to black */
2305     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2306        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2307        checkGLcall("glMaterialfv");
2308     } else {
2309        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2310        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2311        checkGLcall("glMaterialfv");
2312     }
2313     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2314     checkGLcall("glMaterialfv");
2315     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2316     checkGLcall("glMaterialf");
2317
2318     LEAVE_GL();
2319     return D3D_OK;
2320 }
2321
2322 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2323     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2324     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2325     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2326     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2327     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2328     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2329     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2330     return D3D_OK;
2331 }
2332
2333 /*****
2334  * Get / Set Indices
2335  *****/
2336 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2337                                              UINT BaseVertexIndex) {
2338     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
2339     IWineD3DIndexBuffer *oldIdxs;
2340
2341     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2342     oldIdxs = This->updateStateBlock->pIndexData;
2343
2344     This->updateStateBlock->changed.indices = TRUE;
2345     This->updateStateBlock->set.indices = TRUE;
2346     This->updateStateBlock->pIndexData = pIndexData;
2347     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2348
2349     /* Handle recording of state blocks */
2350     if (This->isRecordingState) {
2351         TRACE("Recording... not performing anything\n");
2352         return D3D_OK;
2353     }
2354
2355     if (pIndexData) {
2356         IUnknown *indexBufferParent;
2357         /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2358         IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2359     }
2360     if (oldIdxs) {
2361         IUnknown *indexBufferParent;
2362         IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2363         IUnknown_Release(indexBufferParent);
2364         IUnknown_Release(indexBufferParent);
2365     }
2366     return D3D_OK;
2367 }
2368
2369 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2370     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2371
2372     *ppIndexData = This->stateBlock->pIndexData;
2373
2374     /* up ref count on ppindexdata */
2375     if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2376     *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2377
2378     return D3D_OK;
2379 }
2380
2381 /*****
2382  * Get / Set Viewports
2383  *****/
2384 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2385     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2386
2387     TRACE("(%p)\n", This);
2388     This->updateStateBlock->changed.viewport = TRUE;
2389     This->updateStateBlock->set.viewport = TRUE;
2390     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2391
2392     /* Handle recording of state blocks */
2393     if (This->isRecordingState) {
2394         TRACE("Recording... not performing anything\n");
2395         return D3D_OK;
2396     }
2397
2398     ENTER_GL();
2399
2400     TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2401           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2402
2403     glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2404     checkGLcall("glDepthRange");
2405     /* Note: GL requires lower left, DirectX supplies upper left */
2406     /* TODO: replace usage of renderTarget with context management */
2407     glViewport(pViewport->X,
2408                (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2409                pViewport->Width, pViewport->Height);
2410
2411     checkGLcall("glViewport");
2412
2413     LEAVE_GL();
2414
2415     return D3D_OK;
2416
2417 }
2418
2419 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2420     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2421     TRACE("(%p)\n", This);
2422     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2423     return D3D_OK;
2424 }
2425
2426 /*****
2427  * Get / Set Render States
2428  * TODO: Verify against dx9 definitions
2429  *****/
2430 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2431
2432     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
2433     DWORD                OldValue = This->stateBlock->renderState[State];
2434
2435     /* Simple way of referring to either a DWORD or a 4 byte float */
2436     union {
2437         DWORD d;
2438         float f;
2439     } tmpvalue;
2440
2441     TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2442     This->updateStateBlock->changed.renderState[State] = TRUE;
2443     This->updateStateBlock->set.renderState[State] = TRUE;
2444     This->updateStateBlock->renderState[State] = Value;
2445
2446     /* Handle recording of state blocks */
2447     if (This->isRecordingState) {
2448         TRACE("Recording... not performing anything\n");
2449         return D3D_OK;
2450     }
2451
2452     ENTER_GL();
2453
2454     switch (State) {
2455     case WINED3DRS_FILLMODE                  :
2456         switch ((D3DFILLMODE) Value) {
2457         case D3DFILL_POINT               : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2458         case D3DFILL_WIREFRAME           : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2459         case D3DFILL_SOLID               : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2460         default:
2461             FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2462         }
2463         checkGLcall("glPolygonMode (fillmode)");
2464         break;
2465
2466     case WINED3DRS_LIGHTING                  :
2467         if (Value) {
2468             glEnable(GL_LIGHTING);
2469             checkGLcall("glEnable GL_LIGHTING");
2470         } else {
2471             glDisable(GL_LIGHTING);
2472             checkGLcall("glDisable GL_LIGHTING");
2473         }
2474         break;
2475
2476     case WINED3DRS_ZENABLE                   :
2477         switch ((D3DZBUFFERTYPE) Value) {
2478         case D3DZB_FALSE:
2479             glDisable(GL_DEPTH_TEST);
2480             checkGLcall("glDisable GL_DEPTH_TEST");
2481             break;
2482         case D3DZB_TRUE:
2483             glEnable(GL_DEPTH_TEST);
2484             checkGLcall("glEnable GL_DEPTH_TEST");
2485             break;
2486         case D3DZB_USEW:
2487             glEnable(GL_DEPTH_TEST);
2488             checkGLcall("glEnable GL_DEPTH_TEST");
2489             FIXME("W buffer is not well handled\n");
2490             break;
2491         default:
2492             FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2493         }
2494         break;
2495
2496     case WINED3DRS_CULLMODE                  :
2497
2498         /* If we are culling "back faces with clockwise vertices" then
2499            set front faces to be counter clockwise and enable culling
2500            of back faces                                               */
2501         switch ((D3DCULL) Value) {
2502         case D3DCULL_NONE:
2503             glDisable(GL_CULL_FACE);
2504             checkGLcall("glDisable GL_CULL_FACE");
2505             break;
2506         case D3DCULL_CW:
2507             glEnable(GL_CULL_FACE);
2508             checkGLcall("glEnable GL_CULL_FACE");
2509             if (This->renderUpsideDown) {
2510                 glFrontFace(GL_CW);
2511                 checkGLcall("glFrontFace GL_CW");
2512             } else {
2513                 glFrontFace(GL_CCW);
2514                 checkGLcall("glFrontFace GL_CCW");
2515             }
2516             glCullFace(GL_BACK);
2517             break;
2518         case D3DCULL_CCW:
2519             glEnable(GL_CULL_FACE);
2520             checkGLcall("glEnable GL_CULL_FACE");
2521             if (This->renderUpsideDown) {
2522                 glFrontFace(GL_CCW);
2523                 checkGLcall("glFrontFace GL_CCW");
2524             } else {
2525                 glFrontFace(GL_CW);
2526                 checkGLcall("glFrontFace GL_CW");
2527             }
2528             glCullFace(GL_BACK);
2529             break;
2530         default:
2531             FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2532         }
2533         break;
2534
2535     case WINED3DRS_SHADEMODE                 :
2536         switch ((D3DSHADEMODE) Value) {
2537         case D3DSHADE_FLAT:
2538             glShadeModel(GL_FLAT);
2539             checkGLcall("glShadeModel");
2540             break;
2541         case D3DSHADE_GOURAUD:
2542             glShadeModel(GL_SMOOTH);
2543             checkGLcall("glShadeModel");
2544             break;
2545         case D3DSHADE_PHONG:
2546             FIXME("D3DSHADE_PHONG isn't supported?\n");
2547
2548             LEAVE_GL();
2549             return D3DERR_INVALIDCALL;
2550         default:
2551             FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2552         }
2553         break;
2554
2555     case WINED3DRS_DITHERENABLE              :
2556         if (Value) {
2557             glEnable(GL_DITHER);
2558             checkGLcall("glEnable GL_DITHER");
2559         } else {
2560             glDisable(GL_DITHER);
2561             checkGLcall("glDisable GL_DITHER");
2562         }
2563         break;
2564
2565     case WINED3DRS_ZWRITEENABLE              :
2566         if (Value) {
2567             glDepthMask(1);
2568             checkGLcall("glDepthMask");
2569         } else {
2570             glDepthMask(0);
2571             checkGLcall("glDepthMask");
2572         }
2573         break;
2574
2575     case WINED3DRS_ZFUNC                     :
2576         {
2577             int glParm = GL_LESS;
2578
2579             switch ((D3DCMPFUNC) Value) {
2580             case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2581             case D3DCMP_LESS:          glParm=GL_LESS; break;
2582             case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2583             case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2584             case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2585             case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2586             case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2587             case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2588             default:
2589                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2590             }
2591             glDepthFunc(glParm);
2592             checkGLcall("glDepthFunc");
2593         }
2594         break;
2595
2596     case WINED3DRS_AMBIENT                   :
2597         {
2598             float col[4];
2599             D3DCOLORTOGLFLOAT4(Value, col);
2600             TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2601             glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2602             checkGLcall("glLightModel for MODEL_AMBIENT");
2603
2604         }
2605         break;
2606
2607     case WINED3DRS_ALPHABLENDENABLE          :
2608         if (Value) {
2609             glEnable(GL_BLEND);
2610             checkGLcall("glEnable GL_BLEND");
2611         } else {
2612             glDisable(GL_BLEND);
2613             checkGLcall("glDisable GL_BLEND");
2614         };
2615         break;
2616
2617     case WINED3DRS_SRCBLEND                  :
2618     case WINED3DRS_DESTBLEND                 :
2619         {
2620             int newVal = GL_ZERO;
2621             switch (Value) {
2622             case D3DBLEND_ZERO               : newVal = GL_ZERO;  break;
2623             case D3DBLEND_ONE                : newVal = GL_ONE;  break;
2624             case D3DBLEND_SRCCOLOR           : newVal = GL_SRC_COLOR;  break;
2625             case D3DBLEND_INVSRCCOLOR        : newVal = GL_ONE_MINUS_SRC_COLOR;  break;
2626             case D3DBLEND_SRCALPHA           : newVal = GL_SRC_ALPHA;  break;
2627             case D3DBLEND_INVSRCALPHA        : newVal = GL_ONE_MINUS_SRC_ALPHA;  break;
2628             case D3DBLEND_DESTALPHA          : newVal = GL_DST_ALPHA;  break;
2629             case D3DBLEND_INVDESTALPHA       : newVal = GL_ONE_MINUS_DST_ALPHA;  break;
2630             case D3DBLEND_DESTCOLOR          : newVal = GL_DST_COLOR;  break;
2631             case D3DBLEND_INVDESTCOLOR       : newVal = GL_ONE_MINUS_DST_COLOR;  break;
2632             case D3DBLEND_SRCALPHASAT        : newVal = GL_SRC_ALPHA_SATURATE;  break;
2633
2634             case D3DBLEND_BOTHSRCALPHA       : newVal = GL_SRC_ALPHA;
2635                 This->srcBlend = newVal;
2636                 This->dstBlend = newVal;
2637                 break;
2638
2639             case D3DBLEND_BOTHINVSRCALPHA    : newVal = GL_ONE_MINUS_SRC_ALPHA;
2640                 This->srcBlend = newVal;
2641                 This->dstBlend = newVal;
2642                 break;
2643             default:
2644                 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2645             }
2646
2647             if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2648             if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2649             TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2650             glBlendFunc(This->srcBlend, This->dstBlend);
2651
2652             checkGLcall("glBlendFunc");
2653         }
2654         break;
2655
2656     case WINED3DRS_ALPHATESTENABLE           :
2657         if (Value) {
2658             glEnable(GL_ALPHA_TEST);
2659             checkGLcall("glEnable GL_ALPHA_TEST");
2660         } else {
2661             glDisable(GL_ALPHA_TEST);
2662             checkGLcall("glDisable GL_ALPHA_TEST");
2663         }
2664         break;
2665
2666     case WINED3DRS_ALPHAFUNC                 :
2667         {
2668             int glParm = GL_LESS;
2669             float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2670
2671             switch ((D3DCMPFUNC) Value) {
2672             case D3DCMP_NEVER:         glParm = GL_NEVER; break;
2673             case D3DCMP_LESS:          glParm = GL_LESS; break;
2674             case D3DCMP_EQUAL:         glParm = GL_EQUAL; break;
2675             case D3DCMP_LESSEQUAL:     glParm = GL_LEQUAL; break;
2676             case D3DCMP_GREATER:       glParm = GL_GREATER; break;
2677             case D3DCMP_NOTEQUAL:      glParm = GL_NOTEQUAL; break;
2678             case D3DCMP_GREATEREQUAL:  glParm = GL_GEQUAL; break;
2679             case D3DCMP_ALWAYS:        glParm = GL_ALWAYS; break;
2680             default:
2681                 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2682             }
2683             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2684             glAlphaFunc(glParm, ref);
2685             This->alphafunc = glParm;
2686             checkGLcall("glAlphaFunc");
2687         }
2688         break;
2689
2690     case WINED3DRS_ALPHAREF                  :
2691         {
2692             int glParm = This->alphafunc;
2693             float ref = 1.0f;
2694
2695             ref = ((float) Value) / 255.0f;
2696             TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2697             glAlphaFunc(glParm, ref);
2698             checkGLcall("glAlphaFunc");
2699         }
2700         break;
2701
2702     case WINED3DRS_CLIPPLANEENABLE           :
2703     case WINED3DRS_CLIPPING                  :
2704         {
2705             /* Ensure we only do the changed clip planes */
2706             DWORD enable  = 0xFFFFFFFF;
2707             DWORD disable = 0x00000000;
2708
2709             /* If enabling / disabling all */
2710             if (State == WINED3DRS_CLIPPING) {
2711                 if (Value) {
2712                     enable  = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2713                     disable = 0x00;
2714                 } else {
2715                     disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2716                     enable  = 0x00;
2717                 }
2718             } else {
2719                 enable =   Value & ~OldValue;
2720                 disable = ~Value &  OldValue;
2721             }
2722
2723             if (enable & D3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
2724             if (enable & D3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
2725             if (enable & D3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
2726             if (enable & D3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
2727             if (enable & D3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
2728             if (enable & D3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
2729
2730             if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2731             if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2732             if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2733             if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2734             if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2735             if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2736
2737             /** update clipping status */
2738             if (enable) {
2739               This->stateBlock->clip_status.ClipUnion = 0;
2740               This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2741             } else {
2742               This->stateBlock->clip_status.ClipUnion = 0;
2743               This->stateBlock->clip_status.ClipIntersection = 0;
2744             }
2745         }
2746         break;
2747
2748     case WINED3DRS_BLENDOP                   :
2749         {
2750             int glParm = GL_FUNC_ADD;
2751
2752             switch ((D3DBLENDOP) Value) {
2753             case D3DBLENDOP_ADD              : glParm = GL_FUNC_ADD;              break;
2754             case D3DBLENDOP_SUBTRACT         : glParm = GL_FUNC_SUBTRACT;         break;
2755             case D3DBLENDOP_REVSUBTRACT      : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2756             case D3DBLENDOP_MIN              : glParm = GL_MIN;                   break;
2757             case D3DBLENDOP_MAX              : glParm = GL_MAX;                   break;
2758             default:
2759                 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2760             }
2761             TRACE("glBlendEquation(%x)\n", glParm);
2762             glBlendEquation(glParm);
2763             checkGLcall("glBlendEquation");
2764         }
2765         break;
2766
2767     case WINED3DRS_TEXTUREFACTOR             :
2768         {
2769             unsigned int i;
2770
2771             /* Note the texture color applies to all textures whereas
2772                GL_TEXTURE_ENV_COLOR applies to active only */
2773             float col[4];
2774             D3DCOLORTOGLFLOAT4(Value, col);
2775             /* Set the default alpha blend color */
2776             glBlendColor(col[0], col[1], col[2], col[3]);
2777             checkGLcall("glBlendColor");
2778
2779             /* And now the default texture color as well */
2780             for (i = 0; i < GL_LIMITS(textures); i++) {
2781
2782                 /* Note the D3DRS value applies to all textures, but GL has one
2783                    per texture, so apply it now ready to be used!               */
2784                 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2785                     GLACTIVETEXTURE(i);
2786                 } else if (i>0) {
2787                     FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2788                 }
2789
2790                 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2791                 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2792             }
2793         }
2794         break;
2795
2796     case WINED3DRS_SPECULARENABLE            :
2797         {
2798             /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2799                and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2800                specular color. This is wrong:
2801                Separate specular color means the specular colour is maintained separately, whereas
2802                single color means it is merged in. However in both cases they are being used to
2803                some extent.
2804                To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2805                NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2806                   running 1.4 yet!
2807              */
2808               if (Value) {
2809                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2810                 checkGLcall("glMaterialfv");
2811                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2812                   glEnable(GL_COLOR_SUM_EXT);
2813                 } else {
2814                   TRACE("Specular colors cannot be enabled in this version of opengl\n");
2815                 }
2816                 checkGLcall("glEnable(GL_COLOR_SUM)");
2817               } else {
2818                 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2819
2820                 /* for the case of enabled lighting: */
2821                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2822                 checkGLcall("glMaterialfv");
2823
2824                 /* for the case of disabled lighting: */
2825                 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2826                   glDisable(GL_COLOR_SUM_EXT);
2827                 } else {
2828                   TRACE("Specular colors cannot be disabled in this version of opengl\n");
2829                 }
2830                 checkGLcall("glDisable(GL_COLOR_SUM)");
2831               }
2832         }
2833         break;
2834
2835     case WINED3DRS_STENCILENABLE             :
2836         if (Value) {
2837             glEnable(GL_STENCIL_TEST);
2838             checkGLcall("glEnable GL_STENCIL_TEST");
2839         } else {
2840             glDisable(GL_STENCIL_TEST);
2841             checkGLcall("glDisable GL_STENCIL_TEST");
2842         }
2843         break;
2844
2845     case WINED3DRS_STENCILFUNC               :
2846         {
2847            int glParm = GL_ALWAYS;
2848            int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2849            GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2850
2851            switch ((D3DCMPFUNC) Value) {
2852            case D3DCMP_NEVER:         glParm=GL_NEVER; break;
2853            case D3DCMP_LESS:          glParm=GL_LESS; break;
2854            case D3DCMP_EQUAL:         glParm=GL_EQUAL; break;
2855            case D3DCMP_LESSEQUAL:     glParm=GL_LEQUAL; break;
2856            case D3DCMP_GREATER:       glParm=GL_GREATER; break;
2857            case D3DCMP_NOTEQUAL:      glParm=GL_NOTEQUAL; break;
2858            case D3DCMP_GREATEREQUAL:  glParm=GL_GEQUAL; break;
2859            case D3DCMP_ALWAYS:        glParm=GL_ALWAYS; break;
2860            default:
2861                FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2862            }
2863            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2864            This->stencilfunc = glParm;
2865            glStencilFunc(glParm, ref, mask);
2866            checkGLcall("glStencilFunc");
2867         }
2868         break;
2869
2870     case WINED3DRS_STENCILREF                :
2871         {
2872            int glParm = This->stencilfunc;
2873            int ref = 0;
2874            GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2875
2876            ref = Value;
2877            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2878            glStencilFunc(glParm, ref, mask);
2879            checkGLcall("glStencilFunc");
2880         }
2881         break;
2882
2883     case WINED3DRS_STENCILMASK               :
2884         {
2885            int glParm = This->stencilfunc;
2886            int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2887            GLuint mask = Value;
2888
2889            TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2890            glStencilFunc(glParm, ref, mask);
2891            checkGLcall("glStencilFunc");
2892         }
2893         break;
2894
2895     case WINED3DRS_STENCILFAIL               :
2896         {
2897             GLenum fail  ;
2898             GLint  zpass ;
2899             GLint  zfail ;
2900
2901             fail = StencilOp(Value);
2902             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2903             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2904             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2905             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2906
2907             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2908             glStencilOp(fail, zfail, zpass);
2909             checkGLcall("glStencilOp(fail, zfail, zpass);");
2910         }
2911         break;
2912     case WINED3DRS_STENCILZFAIL              :
2913         {
2914             GLint  fail  ;
2915             GLint  zpass ;
2916             GLenum zfail ;
2917
2918             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2919             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2920             glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2921             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2922             zfail = StencilOp(Value);
2923
2924             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2925             glStencilOp(fail, zfail, zpass);
2926             checkGLcall("glStencilOp(fail, zfail, zpass);");
2927         }
2928         break;
2929     case WINED3DRS_STENCILPASS               :
2930         {
2931             GLint  fail  ;
2932             GLenum zpass ;
2933             GLint  zfail ;
2934
2935             glGetIntegerv(GL_STENCIL_FAIL, &fail);
2936             checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2937             zpass = StencilOp(Value);
2938             glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2939             checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2940
2941             TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2942             glStencilOp(fail, zfail, zpass);
2943             checkGLcall("glStencilOp(fail, zfail, zpass);");
2944         }
2945         break;
2946
2947     case WINED3DRS_STENCILWRITEMASK          :
2948         {
2949             glStencilMask(Value);
2950             TRACE("glStencilMask(%lu)\n", Value);
2951             checkGLcall("glStencilMask");
2952         }
2953         break;
2954
2955     case WINED3DRS_FOGENABLE                 :
2956         {
2957           if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2958                glEnable(GL_FOG);
2959                checkGLcall("glEnable GL_FOG");
2960             } else {
2961                glDisable(GL_FOG);
2962                checkGLcall("glDisable GL_FOG");
2963             }
2964         }
2965         break;
2966
2967     case WINED3DRS_RANGEFOGENABLE            :
2968         {
2969             if (Value) {
2970               TRACE("Enabled RANGEFOG");
2971             } else {
2972               TRACE("Disabled RANGEFOG");
2973             }
2974         }
2975         break;
2976
2977     case WINED3DRS_FOGCOLOR                  :
2978         {
2979             float col[4];
2980             D3DCOLORTOGLFLOAT4(Value, col);
2981             /* Set the default alpha blend color */
2982             glFogfv(GL_FOG_COLOR, &col[0]);
2983             checkGLcall("glFog GL_FOG_COLOR");
2984         }
2985         break;
2986
2987     case WINED3DRS_FOGTABLEMODE              :
2988         {
2989           glHint(GL_FOG_HINT, GL_NICEST);
2990           switch (Value) {
2991           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2992           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2993           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2994           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2995           default:
2996             FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2997           }
2998           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2999             glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3000           }
3001         }
3002         break;
3003
3004     case WINED3DRS_FOGVERTEXMODE             :
3005         {
3006           glHint(GL_FOG_HINT, GL_FASTEST);
3007           switch (Value) {
3008           case D3DFOG_NONE:    /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3009           case D3DFOG_EXP:     glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3010           case D3DFOG_EXP2:    glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3011           case D3DFOG_LINEAR:  glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3012           default:
3013             FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3014           }
3015           if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3016             glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3017           }
3018         }
3019         break;
3020
3021     case WINED3DRS_FOGSTART                  :
3022         {
3023             tmpvalue.d = Value;
3024             glFogfv(GL_FOG_START, &tmpvalue.f);
3025             checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3026             TRACE("Fog Start == %f\n", tmpvalue.f);
3027         }
3028         break;
3029
3030     case WINED3DRS_FOGEND                    :
3031         {
3032             tmpvalue.d = Value;
3033             glFogfv(GL_FOG_END, &tmpvalue.f);
3034             checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3035             TRACE("Fog End == %f\n", tmpvalue.f);
3036         }
3037         break;
3038
3039     case WINED3DRS_FOGDENSITY                :
3040         {
3041             tmpvalue.d = Value;
3042             glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3043             checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3044         }
3045         break;
3046
3047     case WINED3DRS_VERTEXBLEND               :
3048         {
3049           This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3050           TRACE("Vertex Blending state to %ld\n",  Value);
3051         }
3052         break;
3053
3054     case WINED3DRS_TWEENFACTOR               :
3055         {
3056           tmpvalue.d = Value;
3057           This->updateStateBlock->tween_factor = tmpvalue.f;
3058           TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3059         }
3060         break;
3061
3062     case WINED3DRS_INDEXEDVERTEXBLENDENABLE  :
3063         {
3064           TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3065         }
3066         break;
3067
3068     case WINED3DRS_COLORVERTEX               :
3069     case WINED3DRS_DIFFUSEMATERIALSOURCE     :
3070     case WINED3DRS_SPECULARMATERIALSOURCE    :
3071     case WINED3DRS_AMBIENTMATERIALSOURCE     :
3072     case WINED3DRS_EMISSIVEMATERIALSOURCE    :
3073         {
3074             GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3075
3076             if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3077                 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3078                       This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3079                       This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3080                       This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3081                       This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3082
3083                 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3084                     if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3085                         Parm = GL_AMBIENT_AND_DIFFUSE;
3086                     } else {
3087                         Parm = GL_DIFFUSE;
3088                     }
3089                 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3090                     Parm = GL_AMBIENT;
3091                 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3092                     Parm = GL_EMISSION;
3093                 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3094                     Parm = GL_SPECULAR;
3095                 } else {
3096                     Parm = -1;
3097                 }
3098
3099                 if (Parm == -1) {
3100                     if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3101                 } else {
3102                     This->tracking_color = NEEDS_TRACKING;
3103                     This->tracking_parm  = Parm;
3104                 }
3105
3106             } else {
3107                 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3108             }
3109         }
3110         break;
3111
3112     case WINED3DRS_LINEPATTERN               :
3113         {
3114             union {
3115                 DWORD                 d;
3116                 D3DLINEPATTERN        lp;
3117             } tmppattern;
3118             tmppattern.d = Value;
3119
3120             TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3121
3122             if (tmppattern.lp.wRepeatFactor) {
3123                 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3124                 checkGLcall("glLineStipple(repeat, linepattern)");
3125                 glEnable(GL_LINE_STIPPLE);
3126                 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3127             } else {
3128                 glDisable(GL_LINE_STIPPLE);
3129                 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3130             }
3131         }
3132         break;
3133
3134     case WINED3DRS_ZBIAS                     :
3135         {
3136             if (Value) {
3137                 tmpvalue.d = Value;
3138                 TRACE("ZBias value %f\n", tmpvalue.f);
3139                 glPolygonOffset(0, -tmpvalue.f);
3140                 checkGLcall("glPolygonOffset(0, -Value)");
3141                 glEnable(GL_POLYGON_OFFSET_FILL);
3142                 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3143                 glEnable(GL_POLYGON_OFFSET_LINE);
3144                 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3145                 glEnable(GL_POLYGON_OFFSET_POINT);
3146                 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3147             } else {
3148                 glDisable(GL_POLYGON_OFFSET_FILL);
3149                 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3150                 glDisable(GL_POLYGON_OFFSET_LINE);
3151                 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3152                 glDisable(GL_POLYGON_OFFSET_POINT);
3153                 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3154             }
3155         }
3156         break;
3157
3158     case WINED3DRS_NORMALIZENORMALS          :
3159         if (Value) {
3160             glEnable(GL_NORMALIZE);
3161             checkGLcall("glEnable(GL_NORMALIZE);");
3162         } else {
3163             glDisable(GL_NORMALIZE);
3164             checkGLcall("glDisable(GL_NORMALIZE);");
3165         }
3166         break;
3167
3168     case WINED3DRS_POINTSIZE                 :
3169         tmpvalue.d = Value;
3170         TRACE("Set point size to %f\n", tmpvalue.f);
3171         glPointSize(tmpvalue.f);
3172         checkGLcall("glPointSize(...);");
3173         break;
3174
3175     case WINED3DRS_POINTSIZE_MIN             :
3176         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3177           tmpvalue.d = Value;
3178           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3179           checkGLcall("glPointParameterfEXT(...);");
3180         } else {
3181           FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3182         }
3183         break;
3184
3185     case WINED3DRS_POINTSIZE_MAX             :
3186         if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3187           tmpvalue.d = Value;
3188           GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3189           checkGLcall("glPointParameterfEXT(...);");
3190         } else {
3191           FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3192         }
3193         break;
3194
3195     case WINED3DRS_POINTSCALE_A              :
3196     case WINED3DRS_POINTSCALE_B              :
3197     case WINED3DRS_POINTSCALE_C              :
3198     case WINED3DRS_POINTSCALEENABLE          :
3199         {
3200             /* If enabled, supply the parameters, otherwise fall back to defaults */
3201             if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3202                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3203                 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3204                 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3205                 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3206
3207                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3208                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3209                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3210                 } else {
3211                   TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3212                 }
3213             } else {
3214                 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3215                 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3216                   GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3217                   checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3218                 } else {
3219                   TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3220                 }
3221             }
3222             break;
3223         }
3224
3225     case WINED3DRS_COLORWRITEENABLE          :
3226       {
3227         TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3228               Value & D3DCOLORWRITEENABLE_RED   ? 1 : 0,
3229               Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3230               Value & D3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
3231               Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3232         glColorMask(Value & D3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE,
3233                     Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3234                     Value & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
3235                     Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3236         checkGLcall("glColorMask(...)");
3237       }
3238       break;
3239
3240     case WINED3DRS_LOCALVIEWER               :
3241       {
3242         GLint state = (Value) ? 1 : 0;
3243         TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3244         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3245       }
3246       break;
3247
3248     case WINED3DRS_LASTPIXEL                 :
3249       {
3250         if (Value) {
3251           TRACE("Last Pixel Drawing Enabled\n");
3252         } else {
3253           FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3254         }
3255       }
3256       break;
3257
3258     case WINED3DRS_SOFTWAREVERTEXPROCESSING  :
3259       {
3260         if (Value) {
3261           TRACE("Software Processing Enabled\n");
3262         } else {
3263           TRACE("Software Processing Disabled\n");
3264         }
3265       }
3266       break;
3267
3268       /** not supported */
3269     case WINED3DRS_ZVISIBLE                  :
3270       {
3271         LEAVE_GL();
3272         return D3DERR_INVALIDCALL;
3273       }
3274
3275         /* Unhandled yet...! */
3276     case WINED3DRS_EDGEANTIALIAS             :
3277     case WINED3DRS_WRAP0                     :
3278     case WINED3DRS_WRAP1                     :
3279     case WINED3DRS_WRAP2                     :
3280     case WINED3DRS_WRAP3                     :
3281     case WINED3DRS_WRAP4                     :
3282     case WINED3DRS_WRAP5                     :
3283     case WINED3DRS_WRAP6                     :
3284     case WINED3DRS_WRAP7                     :
3285     case WINED3DRS_POINTSPRITEENABLE         :
3286     case WINED3DRS_MULTISAMPLEANTIALIAS      :
3287     case WINED3DRS_MULTISAMPLEMASK           :
3288     case WINED3DRS_PATCHEDGESTYLE            :
3289     case WINED3DRS_PATCHSEGMENTS             :
3290     case WINED3DRS_DEBUGMONITORTOKEN         :
3291     case WINED3DRS_POSITIONORDER             :
3292     case WINED3DRS_NORMALORDER               :
3293         /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3294         FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3295         break;
3296     default:
3297         FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3298     }
3299
3300     LEAVE_GL();
3301
3302     return D3D_OK;
3303 }
3304
3305 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3306     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3307     TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3308     *pValue = This->stateBlock->renderState[State];
3309     return D3D_OK;
3310 }
3311
3312 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3313     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3314     /**
3315     * SetSampler is designed to allow for more than the standard up to 8 textures
3316     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
3317     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3318     *
3319     * http://developer.nvidia.com/object/General_FAQ.html#t6
3320     *
3321     * There are two new settings for GForce
3322     * the sampler one:
3323     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3324     * and the texture one:
3325     * GL_MAX_TEXTURE_COORDS_ARB.
3326     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3327      ******************/
3328     union {
3329         float f;
3330         DWORD d;
3331     } tmpvalue;
3332
3333     TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3334
3335     if(Sampler >  GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3336         FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3337         return D3DERR_INVALIDCALL;
3338     }
3339
3340     This->updateStateBlock->changed.samplerState[Sampler][Type] = TRUE;
3341     This->updateStateBlock->set.samplerState[Sampler][Type]     = TRUE;
3342     TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3343     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
3344
3345     /* Handle recording of state blocks */
3346     if (This->isRecordingState) {
3347         TRACE("Recording... not performing anything\n");
3348         return D3D_OK;
3349     }
3350
3351     /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
3352     clamping, MIPLOD, etc. This will work for up to 16 samplers.
3353     is this just GL_TEXTURE_2D or is it GL_TEXTURE_1D and GL_TEXTURE_3D as well?
3354     */
3355     ENTER_GL();
3356     VTRACE(("Activating appropriate texture state %ld\n", Sampler));
3357     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3358         GLACTIVETEXTURE(Sampler);
3359     } else if (Sampler > 0) {
3360         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3361     }
3362
3363
3364     switch (Type) {
3365
3366     case WINED3DSAMP_ADDRESSU              : /* 1 */
3367     case WINED3DSAMP_ADDRESSV              : /* 2 */
3368     case WINED3DSAMP_ADDRESSW              : /* 3 */
3369         {
3370             GLint wrapParm = GL_REPEAT;
3371             switch (Value) {
3372             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
3373             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP_TO_EDGE; break;
3374             case D3DTADDRESS_BORDER:
3375               {
3376                 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3377                   wrapParm = GL_CLAMP_TO_BORDER_ARB;
3378                 } else {
3379                   /* FIXME: Not right, but better */
3380                   TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3381                   wrapParm = GL_REPEAT;
3382                 }
3383               }
3384               break;
3385             case D3DTADDRESS_MIRROR:
3386               {
3387                 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3388                   wrapParm = GL_MIRRORED_REPEAT_ARB;
3389                 } else {
3390                   /* Unsupported in OpenGL pre-1.4 */
3391                   TRACE("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3392                   wrapParm = GL_REPEAT;
3393                 }
3394               }
3395               break;
3396             case D3DTADDRESS_MIRRORONCE:
3397               {
3398                 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3399                   wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3400                 } else {
3401                   TRACE("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3402                   wrapParm = GL_REPEAT;
3403                 }
3404               }
3405               break;
3406
3407             default:
3408             /* This is for the whole context, not just the sampler,
3409             so we should warn if two states are baing set for any given scene */
3410             if (Type!=0)
3411                 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3412                 wrapParm = GL_REPEAT;
3413             }
3414             switch (Type) {
3415             case WINED3DSAMP_ADDRESSU:
3416                 TRACE("Setting WRAP_S for %ld to %d \n", Sampler, wrapParm);
3417                 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_S, wrapParm);
3418                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3419                 break;
3420             case WINED3DSAMP_ADDRESSV:
3421                 TRACE("Setting WRAP_T for %ld to %d\n", Sampler, wrapParm);
3422                 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_T, wrapParm);
3423                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3424                 break;
3425
3426             case WINED3DSAMP_ADDRESSW:
3427                 TRACE("Setting WRAP_R for %ld to %d\n", Sampler, wrapParm);
3428                 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_R, wrapParm);
3429                 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3430                 break;
3431             default: /* nop */
3432                       break; /** stupic compilator */
3433             }
3434         }
3435         break;
3436
3437     case WINED3DSAMP_BORDERCOLOR           : /* 4 */
3438         {
3439             float col[4];
3440             D3DCOLORTOGLFLOAT4(Value, col);
3441             TRACE("Setting border color for %ld to %lx\n", Sampler, Value);
3442             glTexParameterfv(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_BORDER_COLOR, &col[0]);
3443             checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3444         }
3445         break;
3446
3447       case WINED3DSAMP_MAGFILTER             : /* 5 */
3448       {
3449         DWORD ValueMAG = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAGFILTER];
3450         GLint realVal = GL_NEAREST;
3451
3452         if (ValueMAG == D3DTEXF_POINT) {
3453           realVal = GL_NEAREST;
3454         } else if (ValueMAG == D3DTEXF_LINEAR) {
3455           realVal = GL_LINEAR;
3456         } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3457           if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3458             realVal = GL_LINEAR;
3459           } else {
3460             FIXME("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3461             realVal = GL_NEAREST;
3462           }
3463         } else {
3464           FIXME("Unhandled WINED3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3465           realVal = GL_NEAREST;
3466         }
3467         TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3468         glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAG_FILTER, realVal);
3469         checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3470         /**
3471          * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3472          */
3473         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3474           glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3475                           GL_TEXTURE_MAX_ANISOTROPY_EXT,
3476                           This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3477           checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3478         }
3479       }
3480       break;
3481
3482        case WINED3DSAMP_MINFILTER: /* 6 */
3483        case WINED3DSAMP_MIPFILTER: /* 7 */
3484        {
3485             DWORD ValueMIN = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MINFILTER];
3486             DWORD ValueMIP = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPFILTER];
3487             GLint realVal = GL_LINEAR;
3488
3489             if (ValueMIN == D3DTEXF_NONE) {
3490               /* Doesn't really make sense - Windows just seems to disable
3491                  mipmapping when this occurs                              */
3492               FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3493               realVal = GL_LINEAR;
3494             } else if (ValueMIN == D3DTEXF_POINT) {
3495                 /* GL_NEAREST_* */
3496               if (ValueMIP == D3DTEXF_NONE) {
3497                     realVal = GL_NEAREST;
3498                 } else if (ValueMIP == D3DTEXF_POINT) {
3499                     realVal = GL_NEAREST_MIPMAP_NEAREST;
3500                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3501                     realVal = GL_NEAREST_MIPMAP_LINEAR;
3502                 } else {
3503                     FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3504                     realVal = GL_NEAREST;
3505                 }
3506             } else if (ValueMIN == D3DTEXF_LINEAR) {
3507                 /* GL_LINEAR_* */
3508                 if (ValueMIP == D3DTEXF_NONE) {
3509                     realVal = GL_LINEAR;
3510                 } else if (ValueMIP == D3DTEXF_POINT) {
3511                     realVal = GL_LINEAR_MIPMAP_NEAREST;
3512                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3513                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3514                 } else {
3515                     FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3516                     realVal = GL_LINEAR;
3517                 }
3518             } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3519               if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3520                 if (ValueMIP == D3DTEXF_NONE) {
3521                   realVal = GL_LINEAR_MIPMAP_LINEAR;
3522                 } else if (ValueMIP == D3DTEXF_POINT) {
3523                   realVal = GL_LINEAR_MIPMAP_NEAREST;
3524                 } else if (ValueMIP == D3DTEXF_LINEAR) {
3525                     realVal = GL_LINEAR_MIPMAP_LINEAR;
3526                 } else {
3527                   FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3528                   realVal = GL_LINEAR;
3529                 }
3530               } else {
3531                 WARN("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3532                 realVal = GL_LINEAR;
3533               }
3534             } else {
3535                 FIXME("Unhandled WINED3DTSS_MINFILTER value of %ld\n", ValueMIN);
3536                 realVal = GL_LINEAR_MIPMAP_LINEAR;
3537             }
3538
3539             TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3540             glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MIN_FILTER, realVal);
3541             checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3542             /**
3543              * if we just choose to use ANISOTROPIC filtering, refresh openGL state
3544              */
3545             if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3546               glTexParameteri(This->stateBlock->textureDimensions[Sampler],  GL_TEXTURE_MAX_ANISOTROPY_EXT,
3547                This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3548               checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3549             }
3550         }
3551         break;
3552
3553     case WINED3DSAMP_MIPMAPLODBIAS         : /* 8 */
3554       {
3555         if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3556           tmpvalue.d = Value;
3557           glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3558                     GL_TEXTURE_LOD_BIAS_EXT,
3559                     tmpvalue.f);
3560           checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3561         }
3562       }
3563       break;
3564
3565     case WINED3DSAMP_MAXMIPLEVEL           : /* 9 */
3566       {
3567         /**
3568          * Not really the same, but the more apprioprate than nothing
3569          */
3570         glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3571                         GL_TEXTURE_BASE_LEVEL,
3572                         This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXMIPLEVEL]);
3573         checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3574       }
3575       break;
3576
3577     case WINED3DSAMP_MAXANISOTROPY         :  /* 10 */
3578       {
3579         if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3580           glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3581                           GL_TEXTURE_MAX_ANISOTROPY_EXT,
3582                           This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3583           checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3584         }
3585       }
3586       break;
3587     case WINED3DSAMP_SRGBTEXTURE            : /* 11 */
3588    /* Per texture gamma correction, default 0 */
3589     case WINED3DSAMP_ELEMENTINDEX           : /* 12 */
3590    /* When a multi-element textures is used this indicates the element, (what's a multielement texture?) */
3591     case WINED3DSAMP_DMAPOFFSET             : /* 13 */
3592    /* Value of a precompiled displacement map used by the tesselator, default 0 */
3593         TRACE("Unsupported sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3594     break;
3595     default:
3596
3597         TRACE("invalid sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3598     };
3599     LEAVE_GL();
3600     return D3D_OK;
3601 }
3602
3603 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3604     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3605     /** TODO: check that sampler is in  range **/
3606     *Value = This->updateStateBlock->samplerState[Sampler][Type];
3607     TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3608     return D3D_OK;
3609
3610 }
3611
3612 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3613     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3614     ENTER_GL();
3615
3616     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3617     TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3618     glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3619     LEAVE_GL();
3620     return D3D_OK;
3621 }
3622
3623 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3624     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3625     GLint scissorBox[4];
3626
3627     ENTER_GL();
3628     /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3629     glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3630     pRect->left = scissorBox[1];
3631     pRect->top = scissorBox[2];
3632     pRect->right = scissorBox[1] + scissorBox[3];
3633     pRect->bottom = scissorBox[2] + scissorBox[4];
3634     TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3635     LEAVE_GL();
3636     return D3D_OK;
3637 }
3638
3639 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3640     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3641
3642     TRACE("(%p) : pDecl=%p\n", This, pDecl);
3643
3644     /* TODO: what about recording stateblocks? */
3645     if (NULL != pDecl) {
3646         IWineD3DVertexDeclaration_AddRef(pDecl);
3647     }
3648     if (NULL != This->updateStateBlock->vertexDecl) {
3649       IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3650     }
3651     This->updateStateBlock->vertexDecl = pDecl;
3652     This->updateStateBlock->changed.vertexDecl = TRUE;
3653     This->updateStateBlock->set.vertexDecl = TRUE;
3654     return D3D_OK;
3655 }
3656
3657 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3658     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3659
3660     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3661
3662     *ppDecl = This->updateStateBlock->vertexDecl;
3663     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3664     return D3D_OK;
3665 }
3666
3667 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3668     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3669
3670     static BOOL showFixmes = TRUE;
3671
3672     This->updateStateBlock->vertexShader = pShader;
3673     This->updateStateBlock->changed.vertexShader = TRUE;
3674     This->updateStateBlock->set.vertexShader = TRUE;
3675
3676     if(pShader == NULL) {
3677     /* clear down the shader */
3678         TRACE("Clear down the shader\n");
3679     }else{
3680         if(showFixmes) {
3681             FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3682             showFixmes = FALSE;
3683         }
3684     }
3685
3686     return D3D_OK;
3687
3688     /** FIXME: refernece counting? **/
3689     if (pShader  == NULL) { /* only valid with non FVF shaders */
3690       TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3691       This->updateStateBlock->vertexShader = NULL;
3692     } else {
3693        TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3694       This->updateStateBlock->vertexShader = pShader;
3695     }
3696
3697     This->updateStateBlock->changed.vertexShader = TRUE;
3698     This->updateStateBlock->set.vertexShader = TRUE;
3699
3700     /* Handle recording of state blocks */
3701     if (This->isRecordingState) {
3702       TRACE("Recording... not performing anything\n");
3703       return D3D_OK;
3704     }
3705     /**
3706      * TODO: merge HAL shaders context switching from prototype
3707      */
3708     return D3D_OK;
3709
3710 }
3711
3712 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3713     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3714     *ppShader = This->stateBlock->vertexShader;
3715     if(*ppShader != NULL)
3716         IWineD3DVertexShader_AddRef(*ppShader);
3717     TRACE("(%p) : returning %p\n", This, *ppShader);
3718     return D3D_OK;
3719 }
3720
3721 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL  *pConstantData, UINT BoolCount) {
3722     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3723
3724     TRACE("(%p) : stub\n", This);
3725     return D3D_OK;
3726 }
3727
3728 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL        *pConstantData, UINT BoolCount) {
3729     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3730     TRACE("(%p) : stub\n", This);
3731     return D3D_OK;
3732 }
3733
3734 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int   *pConstantData, UINT Vector4iCount) {
3735     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3736     TRACE("(%p) : stub\n", This);
3737     return D3D_OK;
3738 }
3739
3740 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int         *pConstantData, UINT Vector4iCount) {
3741     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3742     TRACE("(%p) : stub\n", This);
3743     return D3D_OK;
3744 }
3745
3746 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3747     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3748     TRACE("(%p) : stub\n", This);
3749     return D3D_OK;
3750 }
3751
3752 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float       *pConstantData, UINT Vector4fCount) {
3753     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3754     TRACE("(%p) : stub\n", This);
3755     return D3D_OK;
3756 }
3757
3758 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader  *pShader) {
3759     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3760     TRACE("(%p) : stub\n", This);
3761     return D3D_OK;
3762 }
3763
3764 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3765     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3766     TRACE("(%p) : stub\n", This);
3767     return D3D_OK;
3768 }
3769
3770
3771 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL   *pConstantData, UINT BoolCount) {
3772     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3773     TRACE("(%p) : stub\n", This);
3774     return D3D_OK;
3775 }
3776
3777 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL         *pConstantData, UINT BoolCount) {
3778     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3779     TRACE("(%p) : stub\n", This);
3780     return D3D_OK;
3781 }
3782
3783 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int    *pConstantData, UINT Vector4iCount) {
3784     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3785     TRACE("(%p) : stub\n", This);
3786     return D3D_OK;
3787 }
3788
3789 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int          *pConstantData, UINT Vector4iCount) {
3790     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3791     TRACE("(%p) : stub\n", This);
3792     return D3D_OK;
3793 }
3794
3795 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float  *pConstantData, UINT Vector4fCount) {
3796     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3797     TRACE("(%p) : stub\n", This);
3798     return D3D_OK;
3799 }
3800
3801 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float        *pConstantData, UINT Vector4fCount) {
3802     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3803     TRACE("(%p) : stub\n", This);
3804     return D3D_OK;
3805 }
3806
3807 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3808     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3809     FIXME("(%p) : stub\n", This);
3810     return D3D_OK;
3811 }
3812
3813 /*****
3814  * Get / Set Texture Stage States
3815  * TODO: Verify against dx9 definitions
3816  *****/
3817 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3818     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3819
3820     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3821
3822     TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3823
3824     /* Reject invalid texture units */
3825     if (Stage >= GL_LIMITS(textures)) {
3826         TRACE("Attempt to access invalid texture rejected\n");
3827         return D3DERR_INVALIDCALL;
3828     }
3829
3830     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3831     This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3832     This->updateStateBlock->textureState[Stage][Type] = Value;
3833
3834     /* Handle recording of state blocks */
3835     if (This->isRecordingState) {
3836         TRACE("Recording... not performing anything\n");
3837         return D3D_OK;
3838     }
3839
3840     ENTER_GL();
3841
3842     /* Make appropriate texture active */
3843     VTRACE(("Activating appropriate texture state %ld\n", Stage));
3844     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3845         GLACTIVETEXTURE(Stage);
3846     } else if (Stage > 0) {
3847         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3848     }
3849
3850     switch (Type) {
3851     case WINED3DTSS_ALPHAOP               :
3852     case WINED3DTSS_COLOROP               :
3853         {
3854
3855             if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3856                 /* TODO: Disable by making this and all later levels disabled */
3857                 glDisable(GL_TEXTURE_1D);
3858                 checkGLcall("Disable GL_TEXTURE_1D");
3859                 glDisable(GL_TEXTURE_2D);
3860                 checkGLcall("Disable GL_TEXTURE_2D");
3861                 glDisable(GL_TEXTURE_3D);
3862                 checkGLcall("Disable GL_TEXTURE_3D");
3863                 break; /* Don't bother setting the texture operations */
3864             } else {
3865                 /* Enable only the appropriate texture dimension */
3866                 if (Type == WINED3DTSS_COLOROP) {
3867                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3868                         glEnable(GL_TEXTURE_1D);
3869                         checkGLcall("Enable GL_TEXTURE_1D");
3870                     } else {
3871                         glDisable(GL_TEXTURE_1D);
3872                         checkGLcall("Disable GL_TEXTURE_1D");
3873                     }
3874                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3875                       if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3876                         glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3877                         checkGLcall("Enable GL_TEXTURE_2D");
3878                       } else {
3879                         glEnable(GL_TEXTURE_2D);
3880                         checkGLcall("Enable GL_TEXTURE_2D");
3881                       }
3882                     } else {
3883                         glDisable(GL_TEXTURE_2D);
3884                         checkGLcall("Disable GL_TEXTURE_2D");
3885                     }
3886                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3887                         glEnable(GL_TEXTURE_3D);
3888                         checkGLcall("Enable GL_TEXTURE_3D");
3889                     } else {
3890                         glDisable(GL_TEXTURE_3D);
3891                         checkGLcall("Disable GL_TEXTURE_3D");
3892                     }
3893                     if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3894                         glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3895                         checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3896                     } else {
3897                         glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3898                         checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3899                     }
3900                 }
3901             }
3902             /* Drop through... (Except disable case) */
3903         case WINED3DTSS_COLORARG0             :
3904         case WINED3DTSS_COLORARG1             :
3905         case WINED3DTSS_COLORARG2             :
3906         case WINED3DTSS_ALPHAARG0             :
3907         case WINED3DTSS_ALPHAARG1             :
3908         case WINED3DTSS_ALPHAARG2             :
3909             {
3910                 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3911                                    Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3912                 if (isAlphaArg) {
3913                     set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3914                                This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3915                                This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3916                                This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3917                 } else {
3918                     set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3919                                This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3920                                This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3921                                This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3922                 }
3923             }
3924             break;
3925         }
3926
3927     case WINED3DTSS_ADDRESSW              :
3928         {
3929             GLint wrapParm = GL_REPEAT;
3930
3931             switch (Value) {
3932             case D3DTADDRESS_WRAP:   wrapParm = GL_REPEAT; break;
3933             case D3DTADDRESS_CLAMP:  wrapParm = GL_CLAMP_TO_EDGE; break;
3934             case D3DTADDRESS_BORDER:
3935               {
3936                 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3937                   wrapParm = GL_CLAMP_TO_BORDER_ARB;
3938                 } else {
3939                   /* FIXME: Not right, but better */
3940                   FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3941                   wrapParm = GL_REPEAT;
3942                 }
3943               }
3944               break;
3945             case D3DTADDRESS_MIRROR:
3946               {
3947                 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3948                   wrapParm = GL_MIRRORED_REPEAT_ARB;
3949                 } else {
3950                   /* Unsupported in OpenGL pre-1.4 */
3951                   FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3952                   wrapParm = GL_REPEAT;
3953                 }
3954               }
3955               break;
3956             case D3DTADDRESS_MIRRORONCE:
3957               {
3958                 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3959                   wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3960                 } else {
3961                   FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3962                   wrapParm = GL_REPEAT;
3963                 }
3964               }
3965               break;
3966
3967             default:
3968                 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3969                 wrapParm = GL_REPEAT;
3970             }
3971
3972             TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3973             glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3974             checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3975         }
3976         break;
3977
3978     case WINED3DTSS_TEXCOORDINDEX         :
3979         {
3980             /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3981
3982             /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3983                   one flag, you can still specify an index value, which the system uses to
3984                   determine the texture wrapping mode.
3985                   eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3986                   means use the vertex position (camera-space) as the input texture coordinates
3987                   for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3988                   state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3989                   to the TEXCOORDINDEX value */
3990
3991             /**
3992              * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3993              */
3994             switch (Value & 0xFFFF0000) {
3995             case D3DTSS_TCI_PASSTHRU:
3996               /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3997               glDisable(GL_TEXTURE_GEN_S);
3998               glDisable(GL_TEXTURE_GEN_T);
3999               glDisable(GL_TEXTURE_GEN_R);
4000               glDisable(GL_TEXTURE_GEN_Q);
4001               checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
4002               break;
4003
4004             case D3DTSS_TCI_CAMERASPACEPOSITION:
4005               /* CameraSpacePosition means use the vertex position, transformed to camera space,
4006                  as the input texture coordinates for this stage's texture transformation. This
4007                  equates roughly to EYE_LINEAR                                                  */
4008               {
4009                 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4010                 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4011                 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4012                 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4013                 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4014
4015                 glMatrixMode(GL_MODELVIEW);
4016                 glPushMatrix();
4017                 glLoadIdentity();
4018                 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4019                 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4020                 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4021                 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4022                 glPopMatrix();
4023
4024                 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4025                 glEnable(GL_TEXTURE_GEN_S);
4026                 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4027                 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4028                 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4029                 glEnable(GL_TEXTURE_GEN_T);
4030                 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4031                 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4032                 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4033                 glEnable(GL_TEXTURE_GEN_R);
4034                 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4035                 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4036                 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4037               }
4038               break;
4039
4040             case D3DTSS_TCI_CAMERASPACENORMAL:
4041               {
4042                 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4043                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4044                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4045                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4046                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4047                   TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4048
4049                   glMatrixMode(GL_MODELVIEW);
4050                   glPushMatrix();
4051                   glLoadIdentity();
4052                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4053                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4054                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4055                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4056                   glPopMatrix();
4057
4058                   glEnable(GL_TEXTURE_GEN_S);
4059                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4060                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4061                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4062                   glEnable(GL_TEXTURE_GEN_T);
4063                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4064                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4065                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4066                   glEnable(GL_TEXTURE_GEN_R);
4067                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4068                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4069                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4070                 }
4071               }
4072               break;
4073
4074             case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4075               {
4076                 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4077                   float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4078                   float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4079                   float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4080                   float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4081                   TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4082
4083                   glMatrixMode(GL_MODELVIEW);
4084                   glPushMatrix();
4085                   glLoadIdentity();
4086                   glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4087                   glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4088                   glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4089                   glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4090                   glPopMatrix();
4091
4092                   glEnable(GL_TEXTURE_GEN_S);
4093                   checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4094                   glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4095                   checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4096                   glEnable(GL_TEXTURE_GEN_T);
4097                   checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4098                   glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4099                   checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4100                   glEnable(GL_TEXTURE_GEN_R);
4101                   checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4102                   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4103                   checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4104                 }
4105               }
4106               break;
4107
4108             /* Unhandled types: */
4109             default:
4110                 /* Todo: */
4111                 /* ? disable GL_TEXTURE_GEN_n ? */
4112                 glDisable(GL_TEXTURE_GEN_S);
4113                 glDisable(GL_TEXTURE_GEN_T);
4114                 glDisable(GL_TEXTURE_GEN_R);
4115                 glDisable(GL_TEXTURE_GEN_Q);
4116                 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4117                 break;
4118             }
4119         }
4120         break;
4121
4122         /* Unhandled */
4123     case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4124         set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value, (This->stateBlock->textureState[Stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
4125         break;
4126
4127     case WINED3DTSS_BUMPENVMAT00          :
4128     case WINED3DTSS_BUMPENVMAT01          :
4129         TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4130         break;
4131     case WINED3DTSS_BUMPENVMAT10          :
4132     case WINED3DTSS_BUMPENVMAT11          :
4133         TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4134         break;
4135
4136     case WINED3DTSS_BUMPENVLSCALE         :
4137       TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4138       break;
4139
4140     case WINED3DTSS_BUMPENVLOFFSET        :
4141       TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4142       break;
4143
4144     case WINED3DTSS_RESULTARG             :
4145       TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4146       break;
4147
4148     default:
4149         /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4150         TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4151     }
4152
4153     LEAVE_GL();
4154
4155     return D3D_OK;
4156 }
4157
4158 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4159     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4160     TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4161     *pValue = This->updateStateBlock->textureState[Stage][Type];
4162     return D3D_OK;
4163 }
4164
4165 /*****
4166  * Get / Set Texture
4167  *****/
4168 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4169
4170     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4171     IWineD3DBaseTexture   *oldTexture;
4172     BOOL                   reapplyStates = TRUE;
4173     DWORD                  reapplyFlags = 0;
4174     INT                    oldTextureDimensions = -1;
4175     D3DRESOURCETYPE        textureType;
4176
4177     oldTexture = This->updateStateBlock->textures[Stage];
4178     TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4179
4180     /* Reject invalid texture units */
4181     if (Stage >= GL_LIMITS(textures)) {
4182         TRACE("Attempt to access invalid texture rejected\n");
4183         return D3DERR_INVALIDCALL;
4184     }
4185
4186     This->updateStateBlock->set.textures[Stage] = TRUE;
4187     This->updateStateBlock->changed.textures[Stage] = TRUE;
4188     This->updateStateBlock->textures[Stage] = pTexture;
4189
4190     /* Handle recording of state blocks */
4191     if (This->isRecordingState) {
4192         TRACE("Recording... not performing anything\n");
4193         return D3D_OK;
4194     }
4195
4196     oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
4197
4198     ENTER_GL();
4199
4200     /* Make appropriate texture active */
4201     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4202         GLACTIVETEXTURE(Stage);
4203
4204     } else if (Stage>0) {
4205         FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
4206     }
4207
4208     /** NOTE: MSDN says that setTexture increases the reference count,
4209     * and the the application nust set the texture back to null (or have a leaky application),
4210     * This means we should pass the refcount upto the parent
4211      *******************************/
4212     if (NULL != This->updateStateBlock->textures[Stage]) {
4213         IUnknown *textureParent;
4214         IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4215         /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
4216     }
4217
4218     if (NULL != oldTexture) {
4219         IUnknown *textureParent;
4220         IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4221         IUnknown_Release(textureParent);
4222         IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4223         oldTexture = NULL;
4224     }
4225
4226
4227     if (NULL != pTexture) {
4228         /* Now setup the texture appropraitly */
4229         textureType = IWineD3DBaseTexture_GetType(pTexture);
4230
4231         if (textureType == D3DRTYPE_TEXTURE) {
4232
4233           if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4234             TRACE("Skipping setting texture as old == new\n");
4235             reapplyStates = FALSE;
4236
4237           } else {
4238
4239             /* Standard 2D texture */
4240             TRACE("Standard 2d texture\n");
4241             This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
4242
4243             /* Load up the texture now */
4244             IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
4245           }
4246
4247         } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
4248
4249           if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4250               TRACE("Skipping setting texture as old == new\n");
4251               reapplyStates = FALSE;
4252
4253           } else {
4254
4255               /* Standard 3D (volume) texture */
4256               TRACE("Standard 3d texture\n");
4257               This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
4258
4259               /* Load up the texture now */
4260               IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
4261           }
4262
4263         } else if (textureType == D3DRTYPE_CUBETEXTURE) {
4264
4265             if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4266                 TRACE("Skipping setting texture as old == new\n");
4267                 reapplyStates = FALSE;
4268
4269             } else {
4270
4271                 /* Standard Cube texture */
4272                 TRACE("Standard Cube texture\n");
4273                 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
4274
4275                 /* Load up the texture now */
4276                 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
4277             }
4278
4279         } else {
4280             FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
4281         }
4282
4283     } else {
4284
4285         TRACE("Setting to no texture (ie default texture)\n");
4286         This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
4287         glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
4288         checkGLcall("glBindTexture");
4289         TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
4290     }
4291
4292     /* Disable the old texture binding and enable the new one (unless operations are disabled) */
4293     if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4294
4295        glDisable(oldTextureDimensions);
4296        checkGLcall("Disable oldTextureDimensions");
4297
4298        if (This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
4299           glEnable(This->updateStateBlock->textureDimensions[Stage]);
4300           checkGLcall("glEnable new texture dimensions");
4301        }
4302
4303        /* If Alpha arg1 is texture then handle the special case when there changes between a
4304           texture and no texture - See comments in set_tex_op                                  */
4305        if ((This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4306            (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4307        {
4308            reapplyFlags |= REAPPLY_ALPHAOP;
4309        }
4310     }
4311
4312
4313     /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4314        a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4315     if (reapplyStates) {
4316        IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4317     }
4318
4319     LEAVE_GL();
4320     TRACE("Texture now fully setup\n");
4321
4322     return D3D_OK;
4323 }
4324
4325 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4326     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4327     TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4328     *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4329     if (*ppTexture)
4330         IWineD3DBaseTexture_AddRef(*ppTexture);
4331     return D3D_OK;
4332 }
4333
4334 /*****
4335  * Get Back Buffer
4336  *****/
4337 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4338                                                 IWineD3DSurface** ppBackBuffer) {
4339     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4340     IWineD3DSwapChain *swapChain;
4341     HRESULT hr;
4342
4343     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4344
4345     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4346     if(hr == D3D_OK) {
4347         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4348             IWineD3DSwapChain_Release(swapChain);
4349     }else{
4350         *ppBackBuffer = NULL;
4351     }
4352     return hr;
4353 }
4354
4355 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4356     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4357     WARN("(%p) : stub, calling idirect3d for now\n", This);
4358     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4359 }
4360
4361 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4362     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4363     IWineD3DSwapChain *swapChain;
4364     HRESULT hr;
4365
4366     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4367     if (hr == D3D_OK) {
4368         hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4369         IWineD3DSwapChain_Release(swapChain);
4370     }else{
4371         FIXME("(%p) Error getting display mode\n", This);
4372     }
4373     return hr;
4374 }
4375 /*****
4376  * Stateblock related functions
4377  *****/
4378
4379  HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4380     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4381     IWineD3DStateBlockImpl *object;
4382     TRACE("(%p)", This);
4383     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4384     if(NULL == object ) {
4385         FIXME("(%p)Error allocating memory for stateblock\n", This);
4386         return E_OUTOFMEMORY;
4387     }
4388     TRACE("(%p) creted object %p\n", This, object);
4389     object->wineD3DDevice= This;
4390     /** FIXME: object->parent       = parent; **/
4391     object->parent       = NULL;
4392     object->blockType    = WINED3DSBT_ALL;
4393     object->ref          = 1;
4394     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4395
4396     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4397     This->updateStateBlock = object;
4398     This->isRecordingState = TRUE;
4399
4400     TRACE("(%p) recording stateblock %p\n",This , object);
4401     return D3D_OK;
4402 }
4403
4404 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4405     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4406
4407     if (!This->isRecordingState) {
4408         FIXME("(%p) not recording! returning error\n", This);
4409         *ppStateBlock = NULL;
4410         return D3DERR_INVALIDCALL;
4411     }
4412
4413     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4414     This->isRecordingState = FALSE;
4415     This->updateStateBlock = This->stateBlock;
4416     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4417     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4418     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4419     return D3D_OK;
4420 }
4421
4422 /*****
4423  * Scene related functions
4424  *****/
4425 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4426     /* At the moment we have no need for any functionality at the beginning
4427        of a scene                                                          */
4428     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4429     TRACE("(%p) : stub\n", This);
4430     return D3D_OK;
4431 }
4432
4433 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4434     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4435     TRACE("(%p)\n", This);
4436     ENTER_GL();
4437     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4438     glFlush();
4439     checkGLcall("glFlush");
4440
4441     TRACE("End Scene\n");
4442     if(This->renderTarget != NULL) {
4443
4444         /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4445         IUnknown *targetContainer = NULL;
4446         if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4447             || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4448             TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4449             /** always dirtify for now. we must find a better way to see that surface have been modified
4450             (Modifications should will only occur via draw-primitive, but we do need better locking
4451             switching to render-to-texture should remove the overhead though.
4452             */
4453             IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4454             IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4455             IWineD3DSurface_PreLoad(This->renderTarget);
4456             IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4457             IUnknown_Release(targetContainer);
4458         }
4459     }
4460     This->sceneEnded = TRUE;
4461     LEAVE_GL();
4462     return D3D_OK;
4463 }
4464
4465 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4466                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4467                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4468    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4469     IWineD3DSwapChain *swapChain = NULL;
4470     int i;
4471     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4472
4473     TRACE("(%p) Presenting the frame\n", This);
4474
4475     for(i = 0 ; i < swapchains ; i ++) {
4476
4477         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4478         TRACE("presentinng chain %d, %p\n", i, swapChain);
4479         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4480         IWineD3DSwapChain_Release(swapChain);
4481     }
4482
4483     return D3D_OK;
4484 }
4485
4486 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4487                                         DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4488     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4489
4490     /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4491       render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4492       when the depth-buffer format does not contain stencil buffer information, this method fails. */
4493     GLbitfield     glMask = 0;
4494     GLboolean      old_ztest;
4495     GLfloat        old_z_clear_value;
4496     GLint          old_stencil_clear_value;
4497     GLfloat        old_color_clear_value[4];
4498     unsigned int   i;
4499     CONST D3DRECT* curRect;
4500
4501     TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4502           Count, pRects, Flags, Z, Stencil);
4503
4504     ENTER_GL();
4505
4506     glEnable(GL_SCISSOR_TEST);
4507     checkGLcall("glEnable GL_SCISSOR_TEST");
4508
4509     if (Count > 0 && pRects) {
4510         curRect = pRects;
4511     } else {
4512         curRect = NULL;
4513     }
4514
4515     /* Only set the values up once, as they are not changing */
4516     if (Flags & D3DCLEAR_STENCIL) {
4517         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4518         glClearStencil(Stencil);
4519         checkGLcall("glClearStencil");
4520         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4521         glStencilMask(0xFFFFFFFF);
4522     }
4523
4524     if (Flags & D3DCLEAR_ZBUFFER) {
4525         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4526         glDepthMask(GL_TRUE);
4527         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4528         glClearDepth(Z);
4529         checkGLcall("glClearDepth");
4530         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4531     }
4532
4533     if (Flags & D3DCLEAR_TARGET) {
4534         TRACE("Clearing screen with glClear to color %lx\n", Color);
4535         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4536         glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4537                      ((Color >>  8) & 0xFF) / 255.0f,
4538                      ((Color >>  0) & 0xFF) / 255.0f,
4539                      ((Color >> 24) & 0xFF) / 255.0f);
4540         checkGLcall("glClearColor");
4541
4542         /* Clear ALL colors! */
4543         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4544         glMask = glMask | GL_COLOR_BUFFER_BIT;
4545     }
4546
4547     /* Now process each rect in turn */
4548     for (i = 0; i < Count || i == 0; i++) {
4549
4550         if (curRect) {
4551             /* Note gl uses lower left, width/height */
4552             TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4553                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4554                   curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4555                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4556             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4557                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4558             checkGLcall("glScissor");
4559         } else {
4560             glScissor(This->stateBlock->viewport.X,
4561                       (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4562                       This->stateBlock->viewport.Width,
4563                       This->stateBlock->viewport.Height);
4564             checkGLcall("glScissor");
4565         }
4566
4567         /* Clear the selected rectangle (or full screen) */
4568         glClear(glMask);
4569         checkGLcall("glClear");
4570
4571         /* Step to the next rectangle */
4572         if (curRect) curRect = curRect + sizeof(D3DRECT);
4573     }
4574
4575     /* Restore the old values (why..?) */
4576     if (Flags & D3DCLEAR_STENCIL) {
4577         glClearStencil(old_stencil_clear_value);
4578         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4579     }
4580     if (Flags & D3DCLEAR_ZBUFFER) {
4581         glDepthMask(old_ztest);
4582         glClearDepth(old_z_clear_value);
4583     }
4584     if (Flags & D3DCLEAR_TARGET) {
4585         glClearColor(old_color_clear_value[0],
4586                      old_color_clear_value[1],
4587                      old_color_clear_value[2],
4588                      old_color_clear_value[3]);
4589         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4590                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4591                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4592                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4593     }
4594
4595     glDisable(GL_SCISSOR_TEST);
4596     checkGLcall("glDisable");
4597     LEAVE_GL();
4598
4599     return D3D_OK;
4600 }
4601
4602 /*****
4603  * Drawing functions
4604  *****/
4605 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4606                                                 UINT PrimitiveCount) {
4607
4608     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4609     This->stateBlock->streamIsUP = FALSE;
4610
4611     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4612                                debug_d3dprimitivetype(PrimitiveType),
4613                                StartVertex, PrimitiveCount);
4614     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4615
4616     return D3D_OK;
4617 }
4618
4619 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4620 HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4621                                                            D3DPRIMITIVETYPE PrimitiveType,
4622                                                            INT baseVIndex, UINT minIndex,
4623                                                            UINT NumVertices,UINT startIndex,UINT primCount) {
4624
4625     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4626     UINT                 idxStride = 2;
4627     IWineD3DIndexBuffer *pIB;
4628     D3DINDEXBUFFER_DESC  IdxBufDsc;
4629
4630     pIB = This->stateBlock->pIndexData;
4631     This->stateBlock->streamIsUP = FALSE;
4632
4633     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4634           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4635           minIndex, NumVertices, startIndex, baseVIndex, primCount);
4636
4637     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4638     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4639         idxStride = 2;
4640     } else {
4641         idxStride = 4;
4642     }
4643
4644     drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4645                       startIndex, idxStride,
4646                       ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4647                       minIndex);
4648
4649     return D3D_OK;
4650 }
4651
4652 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4653                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4654                                                     UINT VertexStreamZeroStride) {
4655     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656
4657     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4658              debug_d3dprimitivetype(PrimitiveType),
4659              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4660
4661     if (This->stateBlock->streamSource[0] != NULL) {
4662         IUnknown *vertexBufferParent;
4663         IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4664         IUnknown_Release(vertexBufferParent);
4665         IUnknown_Release(vertexBufferParent);
4666     }
4667
4668     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4669     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4670     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4671     This->stateBlock->streamIsUP = TRUE;
4672     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4673     This->stateBlock->streamStride[0] = 0;
4674     This->stateBlock->streamSource[0] = NULL;
4675
4676     /*stream zero settings set to null at end, as per the msdn */
4677     return D3D_OK;
4678 }
4679
4680 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4681                                                              UINT MinVertexIndex,
4682                                                              UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4683                                                              WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4684                                                              UINT VertexStreamZeroStride) {
4685     int                 idxStride;
4686     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4687
4688     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4689              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4690              MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4691              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4692
4693     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4694         idxStride = 2;
4695     } else {
4696         idxStride = 4;
4697     }
4698
4699     if (This->stateBlock->streamSource[0] != NULL) {
4700         IUnknown *vertexBufferParent;
4701         IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4702         This->stateBlock->streamSource[0] = NULL;
4703         IUnknown_Release(vertexBufferParent);
4704         IUnknown_Release(vertexBufferParent);
4705     }
4706
4707     if (This->stateBlock->pIndexData) {
4708         IUnknown *indexBufferParent;
4709         IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4710         This->stateBlock->pIndexData = NULL;
4711         IUnknown_Release(indexBufferParent);
4712         IUnknown_Release(indexBufferParent);
4713     }
4714
4715     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4716     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4717     This->stateBlock->streamIsUP = TRUE;
4718     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4719
4720     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4721
4722     /* stream zero settings set to null at end as per the msdn */
4723     This->stateBlock->streamSource[0] = NULL;
4724     This->stateBlock->streamStride[0] = 0;
4725
4726     return D3D_OK;
4727 }
4728
4729  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4730 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4731     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4732     D3DRESOURCETYPE sourceType;
4733     D3DRESOURCETYPE destinationType;
4734     IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4735     IWineD3DTextureImpl *pSrcTexture  = (IWineD3DTextureImpl *)pSourceTexture;
4736     int i;
4737
4738     sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4739     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4740     if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4741         FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4742         return D3DERR_INVALIDCALL;
4743     }
4744     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4745
4746     /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4747         repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4748         think about moving the code into texture, and adding a member to base texture to occomplish this **/
4749
4750     /* Make sure that the destination texture is loaded */
4751     IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4752     TRACE("Loading source texture\n");
4753
4754     if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4755         FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4756                pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4757     }
4758
4759     if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4760         ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4761
4762         FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4763         return D3DERR_INVALIDCALL;
4764     }
4765     /** TODO: check that both textures have the same number of levels  **/
4766 #if 0
4767     if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4768             return D3DERR_INVALIDCALL;
4769 #endif
4770     /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4771     for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4772         IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4773     }
4774
4775     return D3D_OK;
4776 }
4777
4778 HRESULT  WINAPI  IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4779                                                 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4780                                                 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4781     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4782
4783     TRACE("(%p) : stub\n", This);
4784     return D3D_OK;
4785 }
4786 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4787     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4788
4789     TRACE("(%p) : stub\n", This);
4790     return D3D_OK;
4791 }
4792
4793 HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4794     IWineD3DSwapChain *swapChain;
4795     HRESULT hr;
4796     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4797     if(hr == D3D_OK) {
4798         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4799                 IWineD3DSwapChain_Release(swapChain);
4800     }
4801     return hr;
4802 }
4803
4804 HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4805     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4806     /* return a sensible default */
4807     *pNumPasses = 1;
4808     FIXME("(%p) : stub\n", This);
4809     return D3D_OK;
4810 }
4811
4812 HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4813     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4814     FIXME("(%p) : stub\n", This);
4815     return D3D_OK;
4816 }
4817
4818 HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4819     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4820     FIXME("(%p) : stub\n", This);
4821     return D3D_OK;
4822 }
4823
4824 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4825     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4826     FIXME("(%p) : stub\n", This);
4827     return D3D_OK;
4828 }
4829
4830 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4831     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4832     FIXME("(%p) : stub\n", This);
4833     return D3D_OK;
4834 }
4835
4836 HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4837     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4838     FIXME("(%p) : stub\n", This);
4839     return D3D_OK;
4840 }
4841
4842
4843 BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4844     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4845     FIXME("(%p) : stub\n", This);
4846     return FALSE;
4847 }
4848
4849
4850 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4851     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4852
4853     pRasterStatus->InVBlank = TRUE;
4854     pRasterStatus->ScanLine = 0;
4855     FIXME("(%p) : stub\n", This);
4856     return D3D_OK;
4857 }
4858
4859
4860 HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4861     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4862     static BOOL showfixmes = TRUE;
4863     if(nSegments != 0.0f) {
4864         if( showfixmes) {
4865             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4866             showfixmes = FALSE;
4867         }
4868     }
4869     return D3D_OK;
4870 }
4871
4872 float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4873     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4874     static BOOL showfixmes = TRUE;
4875     if( showfixmes) {
4876         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4877         showfixmes = FALSE;
4878     }
4879     return 0.0f;
4880 }
4881
4882
4883 HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4884     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
4885     /** TODO: remove casts to IWineD3DSurfaceImpl
4886      *       NOTE: move code to surface to accomplish this
4887       ****************************************/
4888     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
4889     int srcWidth, srcHeight;
4890     unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4891     WINED3DFORMAT destFormat, srcFormat;
4892     UINT destSize;
4893     int destLeft, destTop;
4894     D3DPOOL     srcPool, destPool;
4895     int offset    = 0;
4896     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4897     glDescriptor *glDescription = NULL;
4898     GLenum textureDimensions = GL_TEXTURE_2D;
4899     IWineD3DBaseTexture *baseTexture;
4900
4901     WINED3DSURFACE_DESC  winedesc;
4902
4903     memset(&winedesc, 0, sizeof(winedesc));
4904     winedesc.Width  = &srcSurfaceWidth;
4905     winedesc.Height = &srcSurfaceHeight;
4906     winedesc.Pool   = &srcPool;
4907     winedesc.Format = &srcFormat;
4908
4909     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4910
4911     winedesc.Width  = &destSurfaceWidth;
4912     winedesc.Height = &destSurfaceHeight;
4913     winedesc.Pool   = &destPool;
4914     winedesc.Format = &destFormat;
4915     winedesc.Size   = &destSize;
4916
4917     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4918
4919     if(srcPool != D3DPOOL_SYSTEMMEM  || destPool != D3DPOOL_DEFAULT){
4920         FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4921         return D3DERR_INVALIDCALL;
4922     }
4923     /* TODO:  change this to use bindTexture */
4924     /* Make sure the surface is loaded and upto date */
4925     IWineD3DSurface_PreLoad(pDestinationSurface);
4926
4927     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4928
4929     ENTER_GL();
4930
4931     /* this needs to be done in lines if the sourceRect != the sourceWidth */
4932     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
4933     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
4934     destLeft   = pDestPoint  ? pDestPoint->x : 0;
4935     destTop    = pDestPoint  ? pDestPoint->y : 0;
4936
4937
4938     /* This function doesn't support compressed textures
4939     the pitch is just bytesPerPixel * width */
4940
4941     if(srcWidth != srcSurfaceWidth  || (pSourceRect != NULL && pSourceRect->left != 0) ){
4942         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4943         offset   += pSourceRect->left * pSrcSurface->bytesPerPixel;
4944         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4945     }
4946     /* TODO DXT formats */
4947
4948     if(pSourceRect != NULL && pSourceRect->top != 0){
4949        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4950     }
4951     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4952     ,This
4953     ,glDescription->level
4954     ,destLeft
4955     ,destTop
4956     ,srcWidth
4957     ,srcHeight
4958     ,glDescription->glFormat
4959     ,glDescription->glType
4960     ,IWineD3DSurface_GetData(pSourceSurface)
4961     );
4962
4963     /* Sanity check */
4964     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4965     /* need to lock the surface to get the data */
4966        FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4967     }
4968     /* TODO: Cube and volume support */
4969     if(rowoffset != 0){
4970         /* not a whole row so we have to do it a line at a time */
4971         int j;
4972         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4973         unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4974
4975         for(j = destTop ; j < (srcHeight + destTop) ; j++){
4976
4977                 glTexSubImage2D(glDescription->target
4978                     ,glDescription->level
4979                     ,destLeft
4980                     ,j
4981                     ,srcWidth
4982                     ,1
4983                     ,glDescription->glFormat
4984                     ,glDescription->glType
4985                     ,data/* could be quicker using */
4986                 );
4987             data += rowoffset;
4988         }
4989
4990     } else { /* Full width, so just write out the whole texture */
4991
4992         if (WINED3DFMT_DXT1 == destFormat ||
4993             WINED3DFMT_DXT3 == destFormat ||
4994             WINED3DFMT_DXT5 == destFormat) {
4995             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4996                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4997                     /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4998                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
4999                 } if (destFormat != srcFormat) {
5000                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5001                 } else {
5002                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5003                                                         glDescription->level,
5004                                                         glDescription->glFormatInternal,
5005                                                         srcWidth,
5006                                                         srcHeight,
5007                                                         0,
5008                                                         destSize,
5009                                                         IWineD3DSurface_GetData(pSourceSurface));
5010                 }
5011             } else {
5012                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5013             }
5014
5015
5016         } else {
5017             /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5018                to repack the data from pow2Width/Height to expected Width,Height, this makes the
5019                data returned by GetData non-power2 width/height with hardware non-power2
5020                pow2Width/height are set to surface width height, repacking isn't needed so it
5021                doesn't matter which function gets called. */
5022             glTexSubImage2D(glDescription->target
5023                     ,glDescription->level
5024                     ,destLeft
5025                     ,destTop
5026                     ,srcWidth
5027                     ,srcHeight
5028                     ,glDescription->glFormat
5029                     ,glDescription->glType
5030                     ,IWineD3DSurface_GetData(pSourceSurface)
5031                 );
5032
5033         }
5034      }
5035     checkGLcall("glTexSubImage2D");
5036     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5037      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5038      * surface bigger than it needs to be hmm.. */
5039     if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5040         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5041         IWineD3DBaseTexture_Release(baseTexture);
5042     }
5043
5044     glDisable(textureDimensions); /* This needs to be managed better.... */
5045     LEAVE_GL();
5046
5047     return D3D_OK;
5048 }
5049
5050 /* Implementation details at http://developer.nvidia.com/attach/6494
5051 and
5052 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5053 hmm.. no longer supported use
5054 OpenGL evaluators or  tessellate surfaces within your application.
5055 */
5056
5057 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5058 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5059     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5060     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
5061     FIXME("(%p) : Stub\n", This);
5062     return D3D_OK;
5063
5064 }
5065
5066 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5067 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5068     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5069     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
5070     FIXME("(%p) : Stub\n", This);
5071     return D3D_OK;
5072 }
5073
5074 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5075     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5076     TRACE("(%p) Handle(%d)\n", This, Handle);
5077     FIXME("(%p) : Stub\n", This);
5078     return D3D_OK;
5079 }
5080
5081 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5082     /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5083     fill a surface with a block of color!  */
5084     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5085     /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5086     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5087     IWineD3DSwapChainImpl *container = NULL;
5088     BOOL isRenderTarget = FALSE;
5089     unsigned int width, height;
5090     unsigned int top, left;
5091     unsigned int u, v;
5092     DWORD       *data;
5093     TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5094     if (surface->resource.pool != D3DPOOL_DEFAULT) {
5095         FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5096         return D3DERR_INVALIDCALL;
5097     }
5098
5099     /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5100     if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5101         if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5102             /* TODO: make sure we set everything back to the way it was, and context management!
5103                 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5104                 vcheckGLcall("glIntegerv");
5105                 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5106                 vcheckGLcall("glIntegerv");
5107             */
5108             TRACE("Color fill to render targets may cause some graphics issues\n");
5109             if (pSurface == container->frontBuffer) {
5110                 glDrawBuffer(GL_FRONT);
5111             } else {
5112                 glDrawBuffer(GL_BACK);
5113             }
5114         } else {
5115             if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5116                 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
5117             } else {
5118                 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5119             }
5120             if (container != NULL) {
5121                 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5122             }
5123             /* we can use GL_STENCIL_INDEX etc...*/
5124             return D3D_OK;
5125         }
5126         if (container != NULL) {
5127             IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5128         }
5129         isRenderTarget = TRUE;
5130     }
5131     /* TODO: drawing to GL_FRONT and GL_BACK */
5132     /* TODO: see if things can be speeded up by using the correct
5133      * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5134     if (pRect == NULL) {
5135         top    = 0;
5136         left   = 0;
5137         width  = surface->currentDesc.Width;
5138         height = surface->currentDesc.Height;
5139     } else {
5140         left   = pRect->x1;
5141         top    = pRect->y1;
5142         width  = pRect->x2 - left;
5143         height = pRect->y2 - top;
5144     }
5145
5146     data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5147     /* Create a 'line' of color color, in the correct format for the surface */
5148     for (u = 0 ; u < width ; u ++) {
5149             data[u] = color;
5150     }
5151
5152     ENTER_GL();
5153     if (isRenderTarget == FALSE) {
5154         glDescriptor *glDesc;
5155         IWineD3DSurface_PreLoad(pSurface);
5156
5157         /* draw a block of the coloured line on the sufrace */
5158         IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5159         for (v = 0 ; v< height;v++) {
5160             glTexSubImage2D(glDesc->target
5161                             ,glDesc->level /* level */
5162                             ,left
5163                             ,top + v
5164                             ,width
5165                             ,1 /* height */
5166                             ,GL_RGBA
5167                             ,GL_UNSIGNED_BYTE
5168                             ,data
5169                             );
5170         }
5171         checkGLcall("glTexSubImage2D");
5172         /* clean up */
5173         glDisable(glDesc->target);
5174     } else {
5175         /** FIXME: Using GLClear may be faster **/
5176         glRasterPos2i(left, top);
5177         glPixelZoom((float)width ,(float)height);
5178         glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5179         checkGLcall("glDrawPixels");
5180     }
5181     HeapFree(GetProcessHeap(), 0, data);
5182     LEAVE_GL();
5183     return D3D_OK;
5184
5185 }
5186
5187 /* rendertarget and deptth stencil functions */
5188 HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5189     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5190
5191     /* FIXME: Implelent RenderTargetIndex >0 */
5192     if(RenderTargetIndex > 0)
5193         FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5194
5195     *ppRenderTarget = This->renderTarget;
5196     TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5197     /* Note inc ref on returned surface */
5198     if(*ppRenderTarget != NULL)
5199         IWineD3DSurface_AddRef(*ppRenderTarget);
5200     return D3D_OK;
5201 }
5202
5203 HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5204     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5205     *ppZStencilSurface = This->depthStencilBuffer;
5206     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5207
5208     if(*ppZStencilSurface != NULL) {
5209         /* Note inc ref on returned surface */
5210         IWineD3DSurface_AddRef(*ppZStencilSurface);
5211     }
5212     return D3D_OK;
5213 }
5214
5215 /* internal static helper functions */
5216 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5217                                                 IWineD3DSurface *RenderSurface);
5218
5219 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
5220
5221 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
5222
5223 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5224     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5225     HRESULT  hr = D3D_OK;
5226     WINED3DVIEWPORT viewport;
5227
5228     TRACE("(%p) Swapping rendertarget\n",This);
5229     if (RenderTargetIndex > 0) {
5230         FIXME("(%p) Render targets other than the first are not supported\n",This);
5231         RenderTargetIndex = 0;
5232     }
5233
5234     /* MSDN says that null disables the render target
5235     but a device must always be associated with a render target
5236     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5237
5238     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5239     for more details
5240     */
5241     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5242         FIXME("Trying to set render target 0 to NULL\n");
5243         return D3DERR_INVALIDCALL;
5244     }
5245     /* TODO: replace Impl* usage with interface usage */
5246     if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5247         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);
5248         return D3DERR_INVALIDCALL;
5249     }
5250     /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5251      *        builds, but I think wine counts as a 'debug' build for now.
5252       ******************************/
5253     /* If we are trying to set what we already have, don't bother */
5254     if (pRenderTarget == This->renderTarget) {
5255         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5256     } else {
5257         /* Otherwise, set the render target up */
5258
5259         if (FALSE == This->sceneEnded) {
5260             IWineD3DDevice_EndScene(iface);
5261         }
5262         TRACE("clearing renderer\n");
5263         /* IWineD3DDeviceImpl_CleanRender(iface); */
5264         /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5265         depending on the renter target implementation being used.
5266         A shared context implementation will share all buffers between all rendertargets (including swapchains),
5267         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5268         stencil buffer and incure an extra memory overhead */
5269         hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5270     }
5271
5272     if (SUCCEEDED(hr)) {
5273         /* Finally, reset the viewport as the MSDN states. */
5274         /* TODO: Replace impl usage */
5275         viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5276         viewport.Width  = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5277         viewport.X      = 0;
5278         viewport.Y      = 0;
5279         viewport.MaxZ   = 1.0f;
5280         viewport.MinZ   = 0.0f;
5281         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5282     } else {
5283         FIXME("Unknown error setting the render target\n");
5284     }
5285     This->sceneEnded = FALSE;
5286     return hr;
5287 }
5288
5289 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5290     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5291     HRESULT  hr = D3D_OK;
5292     IWineD3DSurface *tmp;
5293
5294     TRACE("(%p) Swapping z-buffer\n",This);
5295
5296     if (pNewZStencil == This->stencilBufferTarget) {
5297         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5298     } else {
5299         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5300         * depending on the renter target implementation being used.
5301         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5302         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5303         * stencil buffer and incure an extra memory overhead
5304          ******************************************************/
5305
5306
5307         tmp = This->stencilBufferTarget;
5308         This->stencilBufferTarget = pNewZStencil;
5309         /* should we be calling the parent or the wined3d surface? */
5310         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5311         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5312         hr = D3D_OK;
5313         /** TODO: glEnable/glDisable on depth/stencil    depending on
5314          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
5315           **********************************************************/
5316     }
5317
5318     return hr;
5319 }
5320
5321
5322 /* Internal functions not in DirectX */
5323  /** TODO: move this off to the opengl context manager
5324  *(the swapchain doesn't need to know anything about offscreen rendering!)
5325   ****************************************************/
5326
5327 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5328 {
5329     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5330
5331     TRACE("(%p), %p\n", This, swapchain);
5332
5333     if (swapchain->win != swapchain->drawable) {
5334         /* Set everything back the way it ws */
5335         swapchain->render_ctx = swapchain->glCtx;
5336         swapchain->drawable   = swapchain->win;
5337     }
5338     return D3D_OK;
5339 }
5340 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5341 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5342     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5343     int i;
5344     unsigned int width;
5345     unsigned int height;
5346     WINED3DFORMAT format;
5347     WINED3DSURFACE_DESC surfaceDesc;
5348     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5349     surfaceDesc.Width  = &width;
5350     surfaceDesc.Height = &height;
5351     surfaceDesc.Format = &format;
5352     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5353     *context = NULL;
5354     /* I need a get width/height function (and should do something with the format) */
5355     for (i = 0; i < CONTEXT_CACHE; ++i) {
5356         /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5357         ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5358         the pSurface can be set to 0 allowing it to be reused from cache **/
5359         if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5360           && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5361             *context = &This->contextCache[i];
5362             break;
5363         }
5364         if (This->contextCache[i].Width == 0) {
5365             This->contextCache[i].pSurface = pSurface;
5366             This->contextCache[i].Width    = width;
5367             This->contextCache[i].Height   = height;
5368             *context = &This->contextCache[i];
5369             break;
5370         }
5371     }
5372     if (i == CONTEXT_CACHE) {
5373         int minUsage = 0x7FFFFFFF; /* MAX_INT */
5374         glContext *dropContext = 0;
5375         for (i = 0; i < CONTEXT_CACHE; i++) {
5376             if (This->contextCache[i].usedcount < minUsage) {
5377                 dropContext = &This->contextCache[i];
5378                 minUsage = This->contextCache[i].usedcount;
5379             }
5380         }
5381         /* clean up the context (this doesn't work for ATI at the moment */
5382 #if 0
5383         glXDestroyContext(swapchain->display, dropContext->context);
5384         glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5385 #endif
5386         FIXME("Leak\n");
5387         dropContext->Width = 0;
5388         dropContext->pSurface = pSurface;
5389         *context = dropContext;
5390     } else {
5391         if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5392           for (i = 0; i < CONTEXT_CACHE; i++) {
5393              This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5394           }
5395         }
5396     }
5397     if (*context != NULL)
5398         return D3D_OK;
5399     else
5400         return E_OUTOFMEMORY;
5401 }
5402
5403 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5404 * the functionality needs splitting up so that we don't do more than we should do.
5405 * this only seems to impact performance a little.
5406  ******************************/
5407 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5408                                                IWineD3DSurface *RenderSurface) {
5409     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5410
5411     IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5412     HRESULT ret =  D3DERR_INVALIDCALL;
5413     IWineD3DSurface *tmp;
5414     /**
5415     * Currently only active for GLX >= 1.3
5416     * for others versions we'll have to use GLXPixmaps
5417     *
5418     * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5419     * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5420     * so only check OpenGL version
5421     * ..........................
5422     * I don't believe that it is a problem with NVidia headers,
5423     * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5424     * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5425     * ATI Note:
5426     * Your application will report GLX version 1.2 on glXQueryVersion.
5427     * However, it is safe to call the GLX 1.3 functions as described below.
5428     */
5429 #if defined(GL_VERSION_1_3)
5430
5431     /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5432     GLXFBConfig* cfgs = NULL;
5433     int nCfgs = 0;
5434     int attribs[256];
5435     int nAttribs = 0;
5436     IWineD3DSwapChain     *currentSwapchain;
5437     IWineD3DSwapChainImpl *swapchain;
5438     /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5439     * but switch them off if the StencilSurface is set to NULL
5440     ** *********************************************************/
5441     D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5442     D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5443
5444     /**TODO:
5445         if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5446         it StencilSurface != NULL && zBufferTarget == NULL switch it on
5447     */
5448
5449 #define PUSH1(att)        attribs[nAttribs++] = (att);
5450 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5451
5452     /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5453
5454     /** TODO: remove the reff to Impl (context manager should fix this!) **/
5455     IWineD3DSwapChainImpl *impSwapChain;
5456     IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5457     if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5458         ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5459     }
5460
5461     ENTER_GL();
5462
5463     PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5464     PUSH2(GLX_X_RENDERABLE,  TRUE);
5465     PUSH2(GLX_DOUBLEBUFFER,  TRUE);
5466     TRACE("calling makeglcfg\n");
5467     D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5468     PUSH1(None);
5469
5470     TRACE("calling chooseFGConfig\n");
5471     cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5472                                                      attribs, &nCfgs);
5473
5474     if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5475         /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5476            why we failed and only show this message once! */
5477         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"); /**/
5478         nAttribs = 0;
5479         PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5480        /* PUSH2(GLX_X_RENDERABLE,  TRUE); */
5481         PUSH2(GLX_RENDER_TYPE,   GLX_RGBA_BIT);
5482         PUSH2(GLX_DOUBLEBUFFER, FALSE);
5483         TRACE("calling makeglcfg\n");
5484         D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5485         PUSH1(None);
5486         cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5487                                                         attribs, &nCfgs);
5488     }
5489
5490     if (NULL != cfgs) {
5491 #ifdef EXTRA_TRACES
5492         int i;
5493         for (i = 0; i < nCfgs; ++i) {
5494             TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5495             debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5496             debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5497         }
5498
5499         if (NULL != This->renderTarget) {
5500             glFlush();
5501             vcheckGLcall("glFlush");
5502             /** This is only useful if the old render target was a swapchain,
5503             * we need to supercede this with a function that displays
5504             * the current buffer on the screen. This is easy to do in glx1.3 but
5505             * we need to do copy-write pixels in glx 1.2.
5506             ************************************************/
5507             glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5508
5509             printf("Hit Enter to get next frame ...\n");
5510             getchar();
5511         }
5512 #endif
5513     }
5514
5515     if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&currentSwapchain) != D3D_OK) {
5516         /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5517         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
5518     }
5519
5520     /**
5521     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5522     *  renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5523      **********************************************************************/
5524     if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5525         /* We also need to make sure that the lights &co are also in the context of the swapchains */
5526         /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5527         TRACE("making swapchain active\n");
5528         if (RenderSurface != This->renderTarget) {
5529             if (RenderSurface ==  swapchain->backBuffer) {
5530             } else {
5531                 /* This could be flagged so that some operations work directly with the front buffer */
5532                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
5533             }
5534             if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5535             == False) {
5536                 TRACE("Error in setting current context: context %p drawable %ld !\n",
5537                        impSwapChain->glCtx, impSwapChain->win);
5538             }
5539
5540             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5541         }
5542         checkGLcall("glXMakeContextCurrent");
5543
5544         IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5545     }
5546     else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5547
5548         /** ********************************************************************
5549         * This is a quickly hacked out implementation of offscreen textures.
5550         * It will work in most cases but there may be problems if the client
5551         * modifies the texture directly, or expects the contents of the rendertarget
5552         * to be persistent.
5553         *
5554         * There are some real speed vs compatibility issues here:
5555         *    we should really use a new context for every texture, but that eats ram.
5556         *    we should also be restoring the texture to the pbuffer but that eats CPU
5557         *    we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5558         *    but if this means reusing the display backbuffer then we need to make sure that
5559         *    states are correctly preserved.
5560         * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5561         * and gain a good performance increase at the cost of compatibility.
5562         * I would suggest that, when this is the case, a user configurable flag be made
5563         * available, allowing the user to choose the best emmulated experience for them.
5564          *********************************************************************/
5565
5566         XVisualInfo *visinfo;
5567         glContext   *newContext;
5568
5569         /* Here were using a shared context model */
5570         if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5571             FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5572         }
5573
5574         /* If the context doesn't exist then create a new one */
5575         /* TODO: This should really be part of findGlContext */
5576         if (NULL == newContext->context) {
5577
5578             TRACE("making new buffer\n");
5579             nAttribs = 0;
5580             PUSH2(GLX_PBUFFER_WIDTH,  newContext->Width);
5581             PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5582             PUSH1(None);
5583
5584             newContext->drawable  = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5585
5586             /** ****************************************
5587             *GLX1.3 isn't supported by XFree 'yet' untill that point ATI emulates pBuffers
5588             *they note:
5589             *   In future releases, we may provide the calls glXCreateNewContext,
5590             *   glXQueryDrawable and glXMakeContextCurrent.
5591             *    so until then we have to use glXGetVisualFromFBConfig &co..
5592             ********************************************/
5593
5594
5595             visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5596             if (!visinfo) {
5597                 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5598             } else {
5599                 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx,  GL_TRUE);
5600                 XFree(visinfo);
5601             }
5602         }
5603         if (NULL == newContext || NULL == newContext->context) {
5604             ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5605         } else {
5606             /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5607             if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5608                 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5609             }
5610
5611             /* Clean up the old context */
5612             IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5613             /* Set the current context of the swapchain to the new context */
5614             impSwapChain->drawable   = newContext->drawable;
5615             impSwapChain->render_ctx = newContext->context;
5616         }
5617     }
5618
5619 #if 0 /* Apply the stateblock to the new context
5620 FIXME: This is a bit of a hack, each context should know it's own state,
5621 the directX current directX state should then be applied to the context */
5622
5623         BOOL oldRecording;
5624         IWineD3DStateBlockImpl *oldUpdateStateBlock;
5625         oldUpdateStateBlock = This->updateStateBlock;
5626         oldRecording= This->isRecordingState;
5627         This->isRecordingState = FALSE;
5628         This->updateStateBlock = This->stateBlock;
5629         IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5630
5631         This->isRecordingState = oldRecording;
5632         This->updateStateBlock = oldUpdateStateBlock;
5633 #endif
5634
5635
5636     /* clean up the current rendertargets swapchain (if it belonged to one) */
5637     if (currentSwapchain != NULL) {
5638         IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5639     }
5640
5641     /* Were done with the opengl context management, setup the rendertargets */
5642
5643     tmp = This->renderTarget;
5644     This->renderTarget = RenderSurface;
5645     IWineD3DSurface_AddRef(This->renderTarget);
5646     IWineD3DSurface_Release(tmp);
5647
5648
5649
5650     {
5651         DWORD value;
5652         /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5653         /* Check that the container is not a swapchain member */
5654
5655         IWineD3DSwapChain *tmpSwapChain;
5656         if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5657             This->renderUpsideDown = TRUE;
5658         }else{
5659             This->renderUpsideDown = FALSE;
5660             IWineD3DSwapChain_Release(tmpSwapChain);
5661         }
5662         /* Force updating the cull mode */
5663         TRACE("setting render state\n");
5664         IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5665         IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5666
5667         /* Force updating projection matrix */
5668         This->last_was_rhw = FALSE;
5669         This->proj_valid = FALSE;
5670     }
5671
5672     ret = D3D_OK;
5673
5674     if (cfgs != NULL) {
5675         XFree(cfgs);
5676     } else {
5677         ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5678             debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5679     }
5680
5681 #undef PUSH1
5682 #undef PUSH2
5683     if ( NULL != impSwapChain) {
5684         IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5685     }
5686     LEAVE_GL();
5687
5688 #endif
5689     return ret;
5690 }
5691
5692 HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5693                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5694     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5695     /* TODO: the use of Impl is deprecated. */
5696     /* some basic validation checks */
5697     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5698
5699     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5700
5701     if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5702       ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5703       return D3DERR_INVALIDCALL;
5704     }
5705     if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5706       ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5707       return D3DERR_INVALIDCALL;
5708     }
5709     /* TODO: make the cursor 'real' */
5710
5711     This->xHotSpot = XHotSpot;
5712     This->yHotSpot = YHotSpot;
5713
5714     return D3D_OK;
5715 }
5716
5717 void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5718     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5719     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5720
5721     This->xScreenSpace = XScreenSpace;
5722     This->yScreenSpace = YScreenSpace;
5723
5724     return;
5725
5726 }
5727
5728 BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5729     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5730     TRACE("(%p) : visible(%d)\n", This, bShow);
5731
5732     This->bCursorVisible = bShow;
5733
5734     return D3D_OK;
5735 }
5736
5737 HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5738     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5739     FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5740     return D3D_OK;
5741 }
5742
5743
5744 HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5745     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5746     /** FIXME: Resource tracking needs to be done,
5747     * The closes we can do to this is set the priorities of all managed textures low
5748     * and then reset them.
5749      ***********************************************************/
5750     FIXME("(%p) : stub\n", This);
5751     return D3D_OK;
5752 }
5753
5754 HRESULT  WINAPI  IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5755     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5756     /** FIXME: Resource trascking needs to be done.
5757     * in effect this pulls all non only default
5758     * textures out of video memory and deletes all glTextures (glDeleteTextures)
5759     * and should clear down the context and set it up according to pPresentationParameters
5760      ***********************************************************/
5761     FIXME("(%p) : stub\n", This);
5762     return D3D_OK;
5763 }
5764
5765 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5766     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5767     /** FIXME: always true at the moment **/
5768     if(bEnableDialogs == FALSE) {
5769         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5770     }
5771     return D3D_OK;
5772 }
5773
5774
5775 HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5776     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5777
5778     FIXME("(%p) : stub\n", This);
5779     /* Setup some reasonable defaults */
5780     pParameters->AdapterOrdinal = 0; /* always for now */
5781     pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5782     pParameters->hFocusWindow = 0;
5783     pParameters->BehaviorFlags =0;
5784     return D3D_OK;
5785 }
5786
5787 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5788     IWineD3DSwapChain *swapchain;
5789     HRESULT hrc = D3D_OK;
5790
5791     TRACE("Relaying  to swapchain\n");
5792
5793     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5794         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5795         IWineD3DSwapChain_Release(swapchain);
5796     }
5797     return;
5798 }
5799
5800 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5801     IWineD3DSwapChain *swapchain;
5802     HRESULT hrc = D3D_OK;
5803
5804     TRACE("Relaying  to swapchain\n");
5805
5806     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5807         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5808         IWineD3DSwapChain_Release(swapchain);
5809     }
5810     return;
5811 }
5812
5813
5814 /** ********************************************************
5815 *   Notification functions
5816 ** ********************************************************/
5817 /** This function must be called in the release of a resource when ref == 0,
5818 * the contents of resource must still be correct,
5819 * any handels to other resource held by the caller must be closed
5820 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5821  *****************************************************/
5822 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5823     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5824     ResourceList* resourceList;
5825
5826     TRACE("(%p) : resource %p\n", This, resource);
5827 #if 0
5828     EnterCriticalSection(&resourceStoreCriticalSection);
5829 #endif
5830     /* add a new texture to the frot of the linked list */
5831     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5832     resourceList->resource = resource;
5833
5834     /* Get the old head */
5835     resourceList->next = This->resources;
5836
5837     This->resources = resourceList;
5838     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5839
5840 #if 0
5841     LeaveCriticalSection(&resourceStoreCriticalSection);
5842 #endif
5843     return;
5844 }
5845
5846 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5847     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5848     ResourceList* resourceList = NULL;
5849     ResourceList* previousResourceList = NULL;
5850     
5851     TRACE("(%p) : resource %p\n", This, resource);
5852
5853 #if 0
5854     EnterCriticalSection(&resourceStoreCriticalSection);
5855 #endif
5856     resourceList = This->resources;
5857
5858     while (resourceList != NULL) {
5859         if(resourceList->resource == resource) break;
5860         previousResourceList = resourceList;
5861         resourceList = resourceList->next;
5862     }
5863
5864     if (resourceList == NULL) {
5865         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5866 #if 0
5867         LeaveCriticalSection(&resourceStoreCriticalSection);
5868 #endif
5869         return;
5870     } else {
5871             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5872     }
5873     /* make sure we don't leave a hole in the list */
5874     if (previousResourceList != NULL) {
5875         previousResourceList->next = resourceList->next;
5876     } else {
5877         This->resources = resourceList->next;
5878     }
5879
5880 #if 0
5881     LeaveCriticalSection(&resourceStoreCriticalSection);
5882 #endif
5883     return;
5884 }
5885
5886
5887 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5888     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5889     int counter;
5890
5891     TRACE("(%p) : resource %p\n", This, resource);
5892     switch(IWineD3DResource_GetType(resource)){
5893         case D3DRTYPE_SURFACE:
5894         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
5895         break;
5896         case D3DRTYPE_TEXTURE:
5897         case D3DRTYPE_CUBETEXTURE:
5898         case D3DRTYPE_VOLUMETEXTURE:
5899                 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5900                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5901                         IUnknown *textureParent;
5902                         IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5903                         /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5904                         FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5905                         IUnknown_Release(textureParent);
5906                         This->stateBlock->textures[counter] = NULL;
5907                     }
5908                     if (This->updateStateBlock != This->stateBlock ){
5909                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5910                             IUnknown *textureParent;
5911                             IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5912                             /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5913                             FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5914                             IUnknown_Release(textureParent);
5915                             This->updateStateBlock->textures[counter] = NULL;
5916                         }
5917                     }
5918                 }
5919         break;
5920         case D3DRTYPE_VOLUME:
5921         /* TODO: nothing really? */
5922         break;
5923         case D3DRTYPE_VERTEXBUFFER:
5924         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5925         {
5926             int streamNumber;
5927             TRACE("Cleaning up stream pointers\n");
5928
5929             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5930                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5931                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5932                 */
5933                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5934                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5935                         FIXME("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
5936                         This->updateStateBlock->streamSource[streamNumber] = 0;
5937                         /* Set changed flag? */
5938                     }
5939                 }
5940                 if (This->stateBlock != NULL ) { /* only happens if their is an error in the application, or on reset/release (because we don't manage internal tracknig properly) */
5941                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5942                         TRACE("Vertex buffer released whlst bound to a state block  stream %d\n", streamNumber);
5943                         This->stateBlock->streamSource[streamNumber] = 0;
5944                     }
5945                 }
5946 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5947                  else { /* This shouldn't happen */
5948                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5949                 }
5950 #endif
5951
5952             }
5953         }
5954         break;
5955         case D3DRTYPE_INDEXBUFFER:
5956         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5957         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5958             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5959                 This->updateStateBlock->pIndexData =  NULL;
5960             }
5961         }
5962         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5963             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5964                 This->stateBlock->pIndexData =  NULL;
5965             }
5966         }
5967
5968         break;
5969         default:
5970         FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
5971         break;
5972     }
5973
5974
5975     /* Remove the resoruce from the resourceStore */
5976     IWineD3DDeviceImpl_RemoveResource(iface, resource);
5977
5978     TRACE("Resource released\n");
5979
5980 }
5981
5982
5983 /** This function is to be called by the swapchain when it is released and it's ref = 0
5984  *****************************************************/
5985 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
5986     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5987     SwapChainList **nextSwapchain;
5988     nextSwapchain = &This->swapchains;
5989
5990     /* Check to see if the swapchian is being used as the render target */
5991     if (This->renderTarget != NULL) {
5992         IWineD3DSurface *swapchainBackBuffer;
5993
5994         IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
5995         if (This->renderTarget == swapchainBackBuffer) {
5996             /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5997             FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
5998         }
5999     }
6000
6001     /* Go through the swapchain list and try to find the swapchain being released */
6002     while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6003         nextSwapchain = &(*nextSwapchain)->next;
6004     }
6005
6006     /* Check to see if we found the swapchain */
6007     if (NULL != *nextSwapchain) {
6008         /* We found the swapchain so remove it from the list */
6009         TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6010         HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6011         *nextSwapchain = (*nextSwapchain)->next;
6012     } else {
6013         /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6014         FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6015     }
6016
6017     TRACE("swapchain (%p) released\n", swapChain);
6018     return;
6019 }
6020
6021 /**********************************************************
6022  * IWineD3DDevice VTbl follows
6023  **********************************************************/
6024
6025 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6026 {
6027     /*** IUnknown methods ***/
6028     IWineD3DDeviceImpl_QueryInterface,
6029     IWineD3DDeviceImpl_AddRef,
6030     IWineD3DDeviceImpl_Release,
6031     /*** IWineD3DDevice methods ***/
6032     IWineD3DDeviceImpl_GetParent,
6033     /*** Creation methods**/
6034     IWineD3DDeviceImpl_CreateVertexBuffer,
6035     IWineD3DDeviceImpl_CreateIndexBuffer,
6036     IWineD3DDeviceImpl_CreateStateBlock,
6037     IWineD3DDeviceImpl_CreateSurface,
6038     IWineD3DDeviceImpl_CreateTexture,
6039     IWineD3DDeviceImpl_CreateVolumeTexture,
6040     IWineD3DDeviceImpl_CreateVolume,
6041     IWineD3DDeviceImpl_CreateCubeTexture,
6042     IWineD3DDeviceImpl_CreateQuery,
6043     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6044     IWineD3DDeviceImpl_CreateVertexDeclaration,
6045     IWineD3DDeviceImpl_CreateVertexShader,
6046     IWineD3DDeviceImpl_CreatePixelShader,
6047
6048     /*** Odd functions **/
6049     IWineD3DDeviceImpl_EvictManagedResources,
6050     IWineD3DDeviceImpl_GetAvailableTextureMem,
6051     IWineD3DDeviceImpl_GetBackBuffer,
6052     IWineD3DDeviceImpl_GetCreationParameters,
6053     IWineD3DDeviceImpl_GetDeviceCaps,
6054     IWineD3DDeviceImpl_GetDirect3D,
6055     IWineD3DDeviceImpl_GetDisplayMode,
6056     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6057     IWineD3DDeviceImpl_GetRasterStatus,
6058     IWineD3DDeviceImpl_GetSwapChain,
6059     IWineD3DDeviceImpl_Reset,
6060     IWineD3DDeviceImpl_SetDialogBoxMode,
6061     IWineD3DDeviceImpl_SetCursorProperties,
6062     IWineD3DDeviceImpl_SetCursorPosition,
6063     IWineD3DDeviceImpl_ShowCursor,
6064     IWineD3DDeviceImpl_TestCooperativeLevel,
6065     /*** Getters and setters **/
6066     IWineD3DDeviceImpl_SetClipPlane,
6067     IWineD3DDeviceImpl_GetClipPlane,
6068     IWineD3DDeviceImpl_SetClipStatus,
6069     IWineD3DDeviceImpl_GetClipStatus,
6070     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6071     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6072     IWineD3DDeviceImpl_SetDepthStencilSurface,
6073     IWineD3DDeviceImpl_GetDepthStencilSurface,
6074     IWineD3DDeviceImpl_SetFVF,
6075     IWineD3DDeviceImpl_GetFVF,
6076     IWineD3DDeviceImpl_SetGammaRamp,
6077     IWineD3DDeviceImpl_GetGammaRamp,
6078     IWineD3DDeviceImpl_SetIndices,
6079     IWineD3DDeviceImpl_GetIndices,
6080     IWineD3DDeviceImpl_SetLight,
6081     IWineD3DDeviceImpl_GetLight,
6082     IWineD3DDeviceImpl_SetLightEnable,
6083     IWineD3DDeviceImpl_GetLightEnable,
6084     IWineD3DDeviceImpl_SetMaterial,
6085     IWineD3DDeviceImpl_GetMaterial,
6086     IWineD3DDeviceImpl_SetNPatchMode,
6087     IWineD3DDeviceImpl_GetNPatchMode,
6088     IWineD3DDeviceImpl_SetPaletteEntries,
6089     IWineD3DDeviceImpl_GetPaletteEntries,
6090     IWineD3DDeviceImpl_SetPixelShader,
6091     IWineD3DDeviceImpl_GetPixelShader,
6092     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6093     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6094     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6095     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6096     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6097     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6098     IWineD3DDeviceImpl_SetRenderState,
6099     IWineD3DDeviceImpl_GetRenderState,
6100     IWineD3DDeviceImpl_SetRenderTarget,
6101     IWineD3DDeviceImpl_GetRenderTarget,
6102     IWineD3DDeviceImpl_SetSamplerState,
6103     IWineD3DDeviceImpl_GetSamplerState,
6104     IWineD3DDeviceImpl_SetScissorRect,
6105     IWineD3DDeviceImpl_GetScissorRect,
6106     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6107     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6108     IWineD3DDeviceImpl_SetStreamSource,
6109     IWineD3DDeviceImpl_GetStreamSource,
6110     IWineD3DDeviceImpl_SetStreamSourceFreq,
6111     IWineD3DDeviceImpl_GetStreamSourceFreq,
6112     IWineD3DDeviceImpl_SetTexture,
6113     IWineD3DDeviceImpl_GetTexture,
6114     IWineD3DDeviceImpl_SetTextureStageState,
6115     IWineD3DDeviceImpl_GetTextureStageState,
6116     IWineD3DDeviceImpl_SetTransform,
6117     IWineD3DDeviceImpl_GetTransform,
6118     IWineD3DDeviceImpl_SetVertexDeclaration,
6119     IWineD3DDeviceImpl_GetVertexDeclaration,
6120     IWineD3DDeviceImpl_SetVertexShader,
6121     IWineD3DDeviceImpl_GetVertexShader,
6122     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6123     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6124     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6125     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6126     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6127     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6128     IWineD3DDeviceImpl_SetViewport,
6129     IWineD3DDeviceImpl_GetViewport,
6130     IWineD3DDeviceImpl_MultiplyTransform,
6131     IWineD3DDeviceImpl_ValidateDevice,
6132     IWineD3DDeviceImpl_ProcessVertices,
6133     /*** State block ***/
6134     IWineD3DDeviceImpl_BeginStateBlock,
6135     IWineD3DDeviceImpl_EndStateBlock,
6136     /*** Scene management ***/
6137     IWineD3DDeviceImpl_BeginScene,
6138     IWineD3DDeviceImpl_EndScene,
6139     IWineD3DDeviceImpl_Present,
6140     IWineD3DDeviceImpl_Clear,
6141     /*** Drawing ***/
6142     IWineD3DDeviceImpl_DrawPrimitive,
6143     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6144     IWineD3DDeviceImpl_DrawPrimitiveUP,
6145     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6146     IWineD3DDeviceImpl_DrawRectPatch,
6147     IWineD3DDeviceImpl_DrawTriPatch,
6148     IWineD3DDeviceImpl_DeletePatch,
6149     IWineD3DDeviceImpl_ColorFill,
6150     IWineD3DDeviceImpl_UpdateTexture,
6151     IWineD3DDeviceImpl_UpdateSurface,
6152     IWineD3DDeviceImpl_StretchRect,
6153     IWineD3DDeviceImpl_GetRenderTargetData,
6154     IWineD3DDeviceImpl_GetFrontBufferData,
6155     /*** Internal use IWineD3DDevice methods ***/
6156     IWineD3DDeviceImpl_SetupTextureStates,
6157     IWineD3DDeviceImpl_SwapChainReleased,
6158     /*** object tracking ***/
6159     IWineD3DDeviceImpl_ResourceReleased
6160 };
6161
6162
6163 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6164     WINED3DRS_ALPHABLENDENABLE   ,
6165     WINED3DRS_ALPHAFUNC          ,
6166     WINED3DRS_ALPHAREF           ,
6167     WINED3DRS_ALPHATESTENABLE    ,
6168     WINED3DRS_BLENDOP            ,
6169     WINED3DRS_COLORWRITEENABLE   ,
6170     WINED3DRS_DESTBLEND          ,
6171     WINED3DRS_DITHERENABLE       ,
6172     WINED3DRS_FILLMODE           ,
6173     WINED3DRS_FOGDENSITY         ,
6174     WINED3DRS_FOGEND             ,
6175     WINED3DRS_FOGSTART           ,
6176     WINED3DRS_LASTPIXEL          ,
6177     WINED3DRS_SHADEMODE          ,
6178     WINED3DRS_SRCBLEND           ,
6179     WINED3DRS_STENCILENABLE      ,
6180     WINED3DRS_STENCILFAIL        ,
6181     WINED3DRS_STENCILFUNC        ,
6182     WINED3DRS_STENCILMASK        ,
6183     WINED3DRS_STENCILPASS        ,
6184     WINED3DRS_STENCILREF         ,
6185     WINED3DRS_STENCILWRITEMASK   ,
6186     WINED3DRS_STENCILZFAIL       ,
6187     WINED3DRS_TEXTUREFACTOR      ,
6188     WINED3DRS_WRAP0              ,
6189     WINED3DRS_WRAP1              ,
6190     WINED3DRS_WRAP2              ,
6191     WINED3DRS_WRAP3              ,
6192     WINED3DRS_WRAP4              ,
6193     WINED3DRS_WRAP5              ,
6194     WINED3DRS_WRAP6              ,
6195     WINED3DRS_WRAP7              ,
6196     WINED3DRS_ZENABLE            ,
6197     WINED3DRS_ZFUNC              ,
6198     WINED3DRS_ZWRITEENABLE
6199 };
6200
6201 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6202     WINED3DTSS_ADDRESSW              ,
6203     WINED3DTSS_ALPHAARG0             ,
6204     WINED3DTSS_ALPHAARG1             ,
6205     WINED3DTSS_ALPHAARG2             ,
6206     WINED3DTSS_ALPHAOP               ,
6207     WINED3DTSS_BUMPENVLOFFSET        ,
6208     WINED3DTSS_BUMPENVLSCALE         ,
6209     WINED3DTSS_BUMPENVMAT00          ,
6210     WINED3DTSS_BUMPENVMAT01          ,
6211     WINED3DTSS_BUMPENVMAT10          ,
6212     WINED3DTSS_BUMPENVMAT11          ,
6213     WINED3DTSS_COLORARG0             ,
6214     WINED3DTSS_COLORARG1             ,
6215     WINED3DTSS_COLORARG2             ,
6216     WINED3DTSS_COLOROP               ,
6217     WINED3DTSS_RESULTARG             ,
6218     WINED3DTSS_TEXCOORDINDEX         ,
6219     WINED3DTSS_TEXTURETRANSFORMFLAGS
6220 };
6221
6222 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6223     WINED3DSAMP_ADDRESSU         ,
6224     WINED3DSAMP_ADDRESSV         ,
6225     WINED3DSAMP_ADDRESSW         ,
6226     WINED3DSAMP_BORDERCOLOR      ,
6227     WINED3DSAMP_MAGFILTER        ,
6228     WINED3DSAMP_MINFILTER        ,
6229     WINED3DSAMP_MIPFILTER        ,
6230     WINED3DSAMP_MIPMAPLODBIAS    ,
6231     WINED3DSAMP_MAXMIPLEVEL      ,
6232     WINED3DSAMP_MAXANISOTROPY    ,
6233     WINED3DSAMP_SRGBTEXTURE      ,
6234     WINED3DSAMP_ELEMENTINDEX
6235 };
6236
6237 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6238     WINED3DRS_AMBIENT                       ,
6239     WINED3DRS_AMBIENTMATERIALSOURCE         ,
6240     WINED3DRS_CLIPPING                      ,
6241     WINED3DRS_CLIPPLANEENABLE               ,
6242     WINED3DRS_COLORVERTEX                   ,
6243     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
6244     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
6245     WINED3DRS_FOGDENSITY                    ,
6246     WINED3DRS_FOGEND                        ,
6247     WINED3DRS_FOGSTART                      ,
6248     WINED3DRS_FOGTABLEMODE                  ,
6249     WINED3DRS_FOGVERTEXMODE                 ,
6250     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
6251     WINED3DRS_LIGHTING                      ,
6252     WINED3DRS_LOCALVIEWER                   ,
6253     WINED3DRS_MULTISAMPLEANTIALIAS          ,
6254     WINED3DRS_MULTISAMPLEMASK               ,
6255     WINED3DRS_NORMALIZENORMALS              ,
6256     WINED3DRS_PATCHEDGESTYLE                ,
6257     WINED3DRS_POINTSCALE_A                  ,
6258     WINED3DRS_POINTSCALE_B                  ,
6259     WINED3DRS_POINTSCALE_C                  ,
6260     WINED3DRS_POINTSCALEENABLE              ,
6261     WINED3DRS_POINTSIZE                     ,
6262     WINED3DRS_POINTSIZE_MAX                 ,
6263     WINED3DRS_POINTSIZE_MIN                 ,
6264     WINED3DRS_POINTSPRITEENABLE             ,
6265     WINED3DRS_RANGEFOGENABLE                ,
6266     WINED3DRS_SPECULARMATERIALSOURCE        ,
6267     WINED3DRS_TWEENFACTOR                   ,
6268     WINED3DRS_VERTEXBLEND
6269 };
6270
6271 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6272     WINED3DTSS_TEXCOORDINDEX         ,
6273     WINED3DTSS_TEXTURETRANSFORMFLAGS
6274 };
6275
6276 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6277     WINED3DSAMP_DMAPOFFSET
6278 };