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