wined3d: Clearing the depth stencil buffer fails without a depth stencil buffer.
[wine] / dlls / wined3d / device.c
1 /*
2  * IWineD3DDevice implementation
3  *
4  * Copyright 2002 Lionel Ulmer
5  * Copyright 2002-2005 Jason Edmeades
6  * Copyright 2003-2004 Raphael Junqueira
7  * Copyright 2004 Christian Costa
8  * Copyright 2005 Oliver Stieber
9  * Copyright 2006 Stefan Dösinger for CodeWeavers
10  * Copyright 2006 Henri Verbeet
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28 #include <stdio.h>
29 #ifdef HAVE_FLOAT_H
30 # include <float.h>
31 #endif
32 #include "wined3d_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
36
37 /* Define the default light parameters as specified by MSDN */
38 const WINED3DLIGHT WINED3D_default_light = {
39
40     WINED3DLIGHT_DIRECTIONAL, /* Type */
41     { 1.0, 1.0, 1.0, 0.0 },   /* Diffuse r,g,b,a */
42     { 0.0, 0.0, 0.0, 0.0 },   /* Specular r,g,b,a */
43     { 0.0, 0.0, 0.0, 0.0 },   /* Ambient r,g,b,a, */
44     { 0.0, 0.0, 0.0 },        /* Position x,y,z */
45     { 0.0, 0.0, 1.0 },        /* Direction x,y,z */
46     0.0,                      /* Range */
47     0.0,                      /* Falloff */
48     0.0, 0.0, 0.0,            /* Attenuation 0,1,2 */
49     0.0,                      /* Theta */
50     0.0                       /* Phi */
51 };
52
53 /* x11drv GDI escapes */
54 #define X11DRV_ESCAPE 6789
55 enum x11drv_escape_codes
56 {
57     X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
58     X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
59     X11DRV_GET_FONT,      /* get current X font for a DC */
60 };
61
62 /* retrieve the X display to use on a given DC */
63 inline static Display *get_display( HDC hdc )
64 {
65     Display *display;
66     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
67
68     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
69                     sizeof(display), (LPSTR)&display )) display = NULL;
70     return display;
71 }
72
73 /* allocate one pbuffer per surface */
74 BOOL pbuffer_per_surface = FALSE;
75
76 /* static function declarations */
77 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
78
79 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil);
80
81 /* helper macros */
82 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
83
84 #define D3DCREATEOBJECTINSTANCE(object, type) { \
85     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
86     D3DMEMCHECK(object, pp##type); \
87     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
88     object->wineD3DDevice = This; \
89     object->parent       = parent; \
90     object->ref          = 1; \
91     *pp##type = (IWineD3D##type *) object; \
92 }
93
94 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
95     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
96     D3DMEMCHECK(object, pp##type); \
97     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
98     object->parent       = parent; \
99     object->ref          = 1; \
100     object->baseShader.device = (IWineD3DDevice*) This; \
101     list_init(&object->baseShader.linked_programs); \
102     *pp##type = (IWineD3D##type *) object; \
103 }
104
105 #define  D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
106     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
107     D3DMEMCHECK(object, pp##type); \
108     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
109     object->resource.wineD3DDevice   = This; \
110     object->resource.parent          = parent; \
111     object->resource.resourceType    = d3dtype; \
112     object->resource.ref             = 1; \
113     object->resource.pool            = Pool; \
114     object->resource.format          = Format; \
115     object->resource.usage           = Usage; \
116     object->resource.size            = _size; \
117     /* Check that we have enough video ram left */ \
118     if (Pool == WINED3DPOOL_DEFAULT) { \
119         if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
120             WARN("Out of 'bogus' video memory\n"); \
121             HeapFree(GetProcessHeap(), 0, object); \
122             *pp##type = NULL; \
123             return WINED3DERR_OUTOFVIDEOMEMORY; \
124         } \
125         globalChangeGlRam(_size); \
126     } \
127     object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
128     if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
129         FIXME("Out of memory!\n"); \
130         HeapFree(GetProcessHeap(), 0, object); \
131         *pp##type = NULL; \
132         return WINED3DERR_OUTOFVIDEOMEMORY; \
133     } \
134     *pp##type = (IWineD3D##type *) object; \
135     IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
136     TRACE("(%p) : Created resource %p\n", This, object); \
137 }
138
139 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
140     _basetexture.levels     = Levels; \
141     _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
142     _basetexture.LOD        = 0; \
143     _basetexture.dirty      = TRUE; \
144 }
145
146 /**********************************************************
147  * Global variable / Constants follow
148  **********************************************************/
149 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
150
151 /**********************************************************
152  * IUnknown parts follows
153  **********************************************************/
154
155 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
156 {
157     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
158
159     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
160     if (IsEqualGUID(riid, &IID_IUnknown)
161         || IsEqualGUID(riid, &IID_IWineD3DBase)
162         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
163         IUnknown_AddRef(iface);
164         *ppobj = This;
165         return S_OK;
166     }
167     *ppobj = NULL;
168     return E_NOINTERFACE;
169 }
170
171 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
172     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
173     ULONG refCount = InterlockedIncrement(&This->ref);
174
175     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
176     return refCount;
177 }
178
179 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
180     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
181     ULONG refCount = InterlockedDecrement(&This->ref);
182
183     TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
184
185     if (!refCount) {
186         if (This->fbo) {
187             GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
188         }
189
190         HeapFree(GetProcessHeap(), 0, This->render_targets);
191
192         HeapFree(GetProcessHeap(), 0, This->draw_buffers);
193
194         if (This->glsl_program_lookup) hash_table_destroy(This->glsl_program_lookup);
195
196         /* TODO: Clean up all the surfaces and textures! */
197         /* NOTE: You must release the parent if the object was created via a callback
198         ** ***************************/
199
200         /* Release the update stateblock */
201         if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
202             if(This->updateStateBlock != This->stateBlock)
203                 FIXME("(%p) Something's still holding the Update stateblock\n",This);
204         }
205         This->updateStateBlock = NULL;
206         { /* because were not doing proper internal refcounts releasing the primary state block
207             causes recursion with the extra checks in ResourceReleased, to avoid this we have
208             to set this->stateBlock = NULL; first */
209             IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
210             This->stateBlock = NULL;
211
212             /* Release the stateblock */
213             if(IWineD3DStateBlock_Release(stateBlock) > 0){
214                     FIXME("(%p) Something's still holding the Update stateblock\n",This);
215             }
216         }
217
218         if (This->resources != NULL ) {
219             FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
220             dumpResources(This->resources);
221         }
222
223         if(This->contexts) ERR("Context array not freed!\n");
224
225         IWineD3D_Release(This->wineD3D);
226         This->wineD3D = NULL;
227         HeapFree(GetProcessHeap(), 0, This);
228         TRACE("Freed device  %p\n", This);
229         This = NULL;
230     }
231     return refCount;
232 }
233
234 /**********************************************************
235  * IWineD3DDevice implementation follows
236  **********************************************************/
237 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
238     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
239     *pParent = This->parent;
240     IUnknown_AddRef(This->parent);
241     return WINED3D_OK;
242 }
243
244 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
245     IWineD3DDeviceImpl *This = object->resource.wineD3DDevice;  /* Needed for GL_EXTCALL */
246     GLenum error, glUsage;
247     DWORD vboUsage = object->resource.usage;
248     if(object->Flags & VBFLAG_VBOCREATEFAIL) {
249         WARN("Creating a vbo failed once, not trying again\n");
250         return;
251     }
252
253     TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p  Usage(%s)\n", object, debug_d3dusage(vboUsage));
254
255     ENTER_GL();
256     /* Make sure that the gl error is cleared. Do not use checkGLcall
257       * here because checkGLcall just prints a fixme and continues. However,
258       * if an error during VBO creation occurs we can fall back to non-vbo operation
259       * with full functionality(but performance loss)
260       */
261     while(glGetError() != GL_NO_ERROR);
262
263     /* Basically the FVF parameter passed to CreateVertexBuffer is no good
264       * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
265       * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
266       * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
267       * to check if the rhw and color values are in the correct format.
268       */
269
270     GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
271     error = glGetError();
272     if(object->vbo == 0 || error != GL_NO_ERROR) {
273         WARN("Failed to create a VBO with error %d\n", error);
274         goto error;
275     }
276
277     GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
278     error = glGetError();
279     if(error != GL_NO_ERROR) {
280         WARN("Failed to bind the VBO, error %d\n", error);
281         goto error;
282     }
283
284     /* Don't use static, because dx apps tend to update the buffer
285      * quite often even if they specify 0 usage. Because we always keep the local copy
286      * we never read from the vbo and can create a write only opengl buffer.
287      */
288     switch(vboUsage & (WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC) ) {
289         case WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC:
290         case WINED3DUSAGE_DYNAMIC:
291             TRACE("Gl usage = GL_STREAM_DRAW\n");
292             glUsage = GL_STREAM_DRAW_ARB;
293             break;
294         case WINED3DUSAGE_WRITEONLY:
295         default:
296             TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
297             glUsage = GL_DYNAMIC_DRAW_ARB;
298             break;
299     }
300
301     /* Reserve memory for the buffer. The amount of data won't change
302      * so we are safe with calling glBufferData once with a NULL ptr and
303      * calling glBufferSubData on updates
304      */
305     GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
306     error = glGetError();
307     if(error != GL_NO_ERROR) {
308         WARN("glBufferDataARB failed with error %d\n", error);
309         goto error;
310     }
311
312     LEAVE_GL();
313
314     return;
315     error:
316     /* Clean up all vbo init, but continue because we can work without a vbo :-) */
317     FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
318     if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
319     object->vbo = 0;
320     object->Flags |= VBFLAG_VBOCREATEFAIL;
321     LEAVE_GL();
322     return;
323 }
324
325 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage, 
326                              DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
327                              IUnknown *parent) {
328     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
329     IWineD3DVertexBufferImpl *object;
330     WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
331     int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
332     BOOL conv;
333
334     if(Size == 0) {
335         WARN("Size 0 requested, returning WINED3DERR_INVALIDCALL\n");
336         *ppVertexBuffer = NULL;
337         return WINED3DERR_INVALIDCALL;
338     }
339
340     D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
341
342     TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
343     *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
344
345     if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
346         object->resource.allocatedMemory  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
347     }
348     object->fvf = FVF;
349
350     /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
351      * drawStridedFast (half-life 2).
352      *
353      * Basically converting the vertices in the buffer is quite expensive, and observations
354      * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
355      * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
356      *
357      * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
358      * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
359      * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
360      * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
361      * dx7 apps.
362      * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
363      * more. In this call we can convert dx7 buffers too.
364      */
365     conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
366     if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && 
367         (dxVersion > 7 || !conv) ) {
368         CreateVBO(object);
369     }
370     return WINED3D_OK;
371 }
372
373 static void CreateIndexBufferVBO(IWineD3DDeviceImpl *This, IWineD3DIndexBufferImpl *object) {
374     GLenum error, glUsage;
375     TRACE("Creating VBO for Index Buffer %p\n", object);
376
377     /* The following code will modify the ELEMENT_ARRAY_BUFFER binding, make sure it is
378      * restored on the next draw
379      */
380     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
381
382     ENTER_GL();
383     while(glGetError());
384
385     GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
386     error = glGetError();
387     if(error != GL_NO_ERROR || object->vbo == 0) {
388         ERR("Creating a vbo failed, continueing without vbo for this buffer\n");
389         goto out;
390     }
391
392     GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->vbo));
393     error = glGetError();
394     if(error != GL_NO_ERROR) {
395         ERR("Failed to bind index buffer, continueing without vbo for this buffer\n");
396         goto out;
397     }
398
399     /* Use static write only usage for now. Dynamic index buffers stay in sysmem, and due to the sysmem
400         * copy no readback will be needed
401         */
402     glUsage = GL_STATIC_DRAW_ARB;
403     GL_EXTCALL(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
404     error = glGetError();
405     if(error != GL_NO_ERROR) {
406         ERR("Failed to initialize the index buffer\n");
407         goto out;
408     }
409     LEAVE_GL();
410     TRACE("Successfully created vbo %d for index buffer %p\n", object->vbo, object);
411     return;
412
413 out:
414     GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
415     GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
416     LEAVE_GL();
417     object->vbo = 0;
418 }
419
420 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage, 
421                                                     WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
422                                                     HANDLE *sharedHandle, IUnknown *parent) {
423     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
424     IWineD3DIndexBufferImpl *object;
425     TRACE("(%p) Creating index buffer\n", This);
426
427     /* Allocate the storage for the device */
428     D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
429
430     if (Pool == WINED3DPOOL_DEFAULT ) { /* We need a local copy for drawStridedSlow */
431         object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
432     }
433
434     if(Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
435         CreateIndexBufferVBO(This, object);
436     }
437
438     TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format, 
439                            debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
440     *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
441
442     return WINED3D_OK;
443 }
444
445 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
446
447     IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
448     IWineD3DStateBlockImpl *object;
449     int i, j;
450     HRESULT temp_result;
451
452     D3DCREATEOBJECTINSTANCE(object, StateBlock)
453     object->blockType     = Type;
454
455     for(i = 0; i < LIGHTMAP_SIZE; i++) {
456         list_init(&object->lightMap[i]);
457     }
458
459     /* Special case - Used during initialization to produce a placeholder stateblock
460           so other functions called can update a state block                         */
461     if (Type == WINED3DSBT_INIT) {
462         /* Don't bother increasing the reference count otherwise a device will never
463            be freed due to circular dependencies                                   */
464         return WINED3D_OK;
465     }
466     
467     temp_result = allocate_shader_constants(object);
468     if (WINED3D_OK != temp_result)
469         return temp_result;
470
471     /* Otherwise, might as well set the whole state block to the appropriate values  */
472     if (This->stateBlock != NULL)
473         stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
474     else
475         memset(object->streamFreq, 1, sizeof(object->streamFreq));
476
477     /* Reset the ref and type after kludging it */
478     object->wineD3DDevice = This;
479     object->ref           = 1;
480     object->blockType     = Type;
481
482     TRACE("Updating changed flags appropriate for type %d\n", Type);
483
484     if (Type == WINED3DSBT_ALL) {
485
486         TRACE("ALL => Pretend everything has changed\n");
487         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
488
489         /* Lights are not part of the changed / set structure */
490         for(j = 0; j < LIGHTMAP_SIZE; j++) {
491             struct list *e;
492             LIST_FOR_EACH(e, &object->lightMap[j]) {
493                 PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
494                 light->changed = TRUE;
495                 light->enabledChanged = TRUE;
496             }
497         }
498     } else if (Type == WINED3DSBT_PIXELSTATE) {
499
500         TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
501         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
502
503         object->changed.pixelShader = TRUE;
504
505         /* Pixel Shader Constants */
506         for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
507             object->changed.pixelShaderConstantsF[i] = TRUE;
508         for (i = 0; i < MAX_CONST_B; ++i)
509             object->changed.pixelShaderConstantsB[i] = TRUE;
510         for (i = 0; i < MAX_CONST_I; ++i)
511             object->changed.pixelShaderConstantsI[i] = TRUE;
512         
513         for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
514             object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
515         }
516         for (j = 0; j < GL_LIMITS(texture_stages); j++) {
517             for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
518                 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
519             }
520         }
521         for (j = 0 ; j < 16; j++) {
522             for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
523
524                 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
525             }
526         }
527
528     } else if (Type == WINED3DSBT_VERTEXSTATE) {
529
530         TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
531         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
532
533         object->changed.vertexShader = TRUE;
534
535         /* Vertex Shader Constants */
536         for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
537             object->changed.vertexShaderConstantsF[i] = TRUE;
538         for (i = 0; i < MAX_CONST_B; ++i)
539             object->changed.vertexShaderConstantsB[i] = TRUE;
540         for (i = 0; i < MAX_CONST_I; ++i)
541             object->changed.vertexShaderConstantsI[i] = TRUE;
542  
543         for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
544             object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
545         }
546         for (j = 0; j < GL_LIMITS(texture_stages); j++) {
547             for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
548                 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
549             }
550         }
551         for (j = 0 ; j < 16; j++){
552             for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
553                 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
554             }
555         }
556
557         for(j = 0; j < LIGHTMAP_SIZE; j++) {
558             struct list *e;
559             LIST_FOR_EACH(e, &object->lightMap[j]) {
560                 PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
561                 light->changed = TRUE;
562                 light->enabledChanged = TRUE;
563             }
564         }
565     } else {
566         FIXME("Unrecognized state block type %d\n", Type);
567     }
568
569     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
570     return WINED3D_OK;
571 }
572
573
574 /* ************************************
575 MSDN:
576 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
577
578 Discard
579  [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. 
580
581 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.
582
583 ******************************** */
584  
585 static HRESULT  WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,WINED3DRESOURCETYPE Type, DWORD Usage, WINED3DPOOL Pool, WINED3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, WINED3DSURFTYPE Impl, IUnknown *parent) {
586     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;    
587     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
588     unsigned int pow2Width, pow2Height;
589     unsigned int Size       = 1;
590     const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
591     TRACE("(%p) Create surface\n",This);
592     
593     /** FIXME: Check ranges on the inputs are valid 
594      * MSDN
595      *   MultisampleQuality
596      *    [in] Quality level. The valid range is between zero and one less than the level
597      *    returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. 
598      *    Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
599      *    values of paired render targets, depth stencil surfaces, and the MultiSample type
600      *    must all match.
601       *******************************/
602
603
604     /**
605     * TODO: Discard MSDN
606     * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
607     *
608     * If this flag is set, the contents of the depth stencil buffer will be
609     * invalid after calling either IDirect3DDevice9::Present or  * IDirect3DDevice9::SetDepthStencilSurface
610     * with a different depth surface.
611     *
612     *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
613     ***************************/
614
615     if(MultisampleQuality < 0) {
616         FIXME("Invalid multisample level %d\n", MultisampleQuality);
617         return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
618     }
619
620     if(MultisampleQuality > 0) {
621         FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
622         MultisampleQuality=0;
623     }
624
625     /** FIXME: Check that the format is supported
626     *    by the device.
627       *******************************/
628
629     /* Non-power2 support */
630     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
631         pow2Width = Width;
632         pow2Height = Height;
633     } else {
634         /* Find the nearest pow2 match */
635         pow2Width = pow2Height = 1;
636         while (pow2Width < Width) pow2Width <<= 1;
637         while (pow2Height < Height) pow2Height <<= 1;
638     }
639
640     if (pow2Width > Width || pow2Height > Height) {
641          /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
642         if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
643                || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
644             FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
645                     This, Width, Height);
646             return WINED3DERR_NOTAVAILABLE;
647         }
648     }
649
650     /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
651      *  it is based around 4x4 pixel blocks it requires padding, so allocate enough
652      *  space!
653       *********************************/
654     if (WINED3DFMT_UNKNOWN == Format) {
655         Size = 0;
656     } else if (Format == WINED3DFMT_DXT1) {
657         /* DXT1 is half byte per pixel */
658        Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4)) >> 1;
659
660     } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
661                Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
662        Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4));
663     } else {
664        /* The pitch is a multiple of 4 bytes */
665        Size = ((Width * tableEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
666        Size *= Height;
667     }
668
669     /** Create and initialise the surface resource **/
670     D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
671     /* "Standalone" surface */
672     IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
673
674     object->currentDesc.Width      = Width;
675     object->currentDesc.Height     = Height;
676     object->currentDesc.MultiSampleType    = MultiSample;
677     object->currentDesc.MultiSampleQuality = MultisampleQuality;
678
679     /* Setup some glformat defaults */
680     object->glDescription.glFormat         = tableEntry->glFormat;
681     object->glDescription.glFormatInternal = tableEntry->glInternal;
682     object->glDescription.glType           = tableEntry->glType;
683
684     object->glDescription.textureName      = 0;
685     object->glDescription.level            = Level;
686     object->glDescription.target           = GL_TEXTURE_2D;
687
688     /* Internal data */
689     object->pow2Width  = pow2Width;
690     object->pow2Height = pow2Height;
691
692     /* Flags */
693     object->Flags      = 0; /* We start without flags set */
694     object->Flags     |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
695     object->Flags     |= Discard ? SFLAG_DISCARD : 0;
696     object->Flags     |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
697     object->Flags     |= Lockable ? SFLAG_LOCKABLE : 0;
698
699
700     if (WINED3DFMT_UNKNOWN != Format) {
701         object->bytesPerPixel = tableEntry->bpp;
702     } else {
703         object->bytesPerPixel = 0;
704     }
705
706     /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
707
708     TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
709
710     /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
711     * this function is too deep to need to care about things like this.
712     * Levels need to be checked too, and possibly Type since they all affect what can be done.
713     * ****************************************/
714     switch(Pool) {
715     case WINED3DPOOL_SCRATCH:
716         if(!Lockable)
717             FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE "
718                 "which are mutually exclusive, setting lockable to TRUE\n");
719                 Lockable = TRUE;
720     break;
721     case WINED3DPOOL_SYSTEMMEM:
722         if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, "
723                                     "this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
724     case WINED3DPOOL_MANAGED:
725         if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a "
726                                                 "Usage of DYNAMIC which are mutually exclusive, not doing "
727                                                 "anything just telling you.\n");
728     break;
729     case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
730         if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
731            && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
732             WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
733     break;
734     default:
735         FIXME("(%p) Unknown pool %d\n", This, Pool);
736     break;
737     };
738
739     if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
740         FIXME("Trying to create a render target that isn't in the default pool\n");
741     }
742
743     /* mark the texture as dirty so that it gets loaded first time around*/
744     IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
745     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
746            This, Width, Height, Format, debug_d3dformat(Format),
747            (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
748
749     /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
750     if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
751         This->ddraw_primary = (IWineD3DSurface *) object;
752
753     /* Look at the implementation and set the correct Vtable */
754     switch(Impl) {
755         case SURFACE_OPENGL:
756             /* Nothing to do, it's set already */
757             break;
758
759         case SURFACE_GDI:
760             object->lpVtbl = &IWineGDISurface_Vtbl;
761             break;
762
763         default:
764             /* To be sure to catch this */
765             ERR("Unknown requested surface implementation %d!\n", Impl);
766             IWineD3DSurface_Release((IWineD3DSurface *) object);
767             return WINED3DERR_INVALIDCALL;
768     }
769
770     /* Call the private setup routine */
771     return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
772
773 }
774
775 static HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
776                                                  DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
777                                                  IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
778                                                  D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
779
780     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
781     IWineD3DTextureImpl *object;
782     unsigned int i;
783     UINT tmpW;
784     UINT tmpH;
785     HRESULT hr;
786     unsigned int pow2Width;
787     unsigned int pow2Height;
788
789
790     TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
791     TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
792             Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
793
794     /* TODO: It should only be possible to create textures for formats 
795              that are reported as supported */
796     if (WINED3DFMT_UNKNOWN >= Format) {
797         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
798         return WINED3DERR_INVALIDCALL;
799     }
800
801     D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
802     D3DINITIALIZEBASETEXTURE(object->baseTexture);    
803     object->width  = Width;
804     object->height = Height;
805
806     /** Non-power2 support **/
807     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
808         pow2Width = Width;
809         pow2Height = Height;
810     } else {
811         /* Find the nearest pow2 match */
812         pow2Width = pow2Height = 1;
813         while (pow2Width < Width) pow2Width <<= 1;
814         while (pow2Height < Height) pow2Height <<= 1;
815     }
816
817     /** FIXME: add support for real non-power-two if it's provided by the video card **/
818     /* Precalculated scaling for 'faked' non power of two texture coords */
819     object->pow2scalingFactorX  =  (((float)Width)  / ((float)pow2Width));
820     object->pow2scalingFactorY  =  (((float)Height) / ((float)pow2Height));
821     TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
822
823     /* Calculate levels for mip mapping */
824     if (Levels == 0) {
825         TRACE("calculating levels %d\n", object->baseTexture.levels);
826         object->baseTexture.levels++;
827         tmpW = Width;
828         tmpH = Height;
829         while (tmpW > 1 || tmpH > 1) {
830             tmpW = max(1, tmpW >> 1);
831             tmpH = max(1, tmpH >> 1);
832             object->baseTexture.levels++;
833         }
834         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
835     }
836
837     /* Generate all the surfaces */
838     tmpW = Width;
839     tmpH = Height;
840     for (i = 0; i < object->baseTexture.levels; i++)
841     {
842         /* use the callback to create the texture surface */
843         hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
844         if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
845             FIXME("Failed to create surface  %p\n", object);
846             /* clean up */
847             object->surfaces[i] = NULL;
848             IWineD3DTexture_Release((IWineD3DTexture *)object);
849
850             *ppTexture = NULL;
851             return hr;
852         }
853
854         IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
855         TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
856         /* calculate the next mipmap level */
857         tmpW = max(1, tmpW >> 1);
858         tmpH = max(1, tmpH >> 1);
859     }
860
861     TRACE("(%p) : Created  texture %p\n", This, object);
862     return WINED3D_OK;
863 }
864
865 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
866                                                       UINT Width, UINT Height, UINT Depth,
867                                                       UINT Levels, DWORD Usage,
868                                                       WINED3DFORMAT Format, WINED3DPOOL Pool,
869                                                       IWineD3DVolumeTexture **ppVolumeTexture,
870                                                       HANDLE *pSharedHandle, IUnknown *parent,
871                                                       D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
872
873     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
874     IWineD3DVolumeTextureImpl *object;
875     unsigned int               i;
876     UINT                       tmpW;
877     UINT                       tmpH;
878     UINT                       tmpD;
879
880     /* TODO: It should only be possible to create textures for formats 
881              that are reported as supported */
882     if (WINED3DFMT_UNKNOWN >= Format) {
883         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
884         return WINED3DERR_INVALIDCALL;
885     }
886
887     D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
888     D3DINITIALIZEBASETEXTURE(object->baseTexture);
889
890     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
891           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
892
893     object->width  = Width;
894     object->height = Height;
895     object->depth  = Depth;
896
897     /* Calculate levels for mip mapping */
898     if (Levels == 0) {
899         object->baseTexture.levels++;
900         tmpW = Width;
901         tmpH = Height;
902         tmpD = Depth;
903         while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
904             tmpW = max(1, tmpW >> 1);
905             tmpH = max(1, tmpH >> 1);
906             tmpD = max(1, tmpD >> 1);
907             object->baseTexture.levels++;
908         }
909         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
910     }
911
912     /* Generate all the surfaces */
913     tmpW = Width;
914     tmpH = Height;
915     tmpD = Depth;
916
917     for (i = 0; i < object->baseTexture.levels; i++)
918     {
919         HRESULT hr;
920         /* Create the volume */
921         hr = D3DCB_CreateVolume(This->parent, parent, Width, Height, Depth, Format, Pool, Usage,
922                                 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
923
924         if(FAILED(hr)) {
925             ERR("Creating a volume for the volume texture failed(%08x)\n", hr);
926             IWineD3DVolumeTexture_Release((IWineD3DVolumeTexture *) object);
927             *ppVolumeTexture = NULL;
928             return hr;
929         }
930
931         /* Set its container to this object */
932         IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
933
934         /* calcualte the next mipmap level */
935         tmpW = max(1, tmpW >> 1);
936         tmpH = max(1, tmpH >> 1);
937         tmpD = max(1, tmpD >> 1);
938     }
939
940     *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
941     TRACE("(%p) : Created volume texture %p\n", This, object);
942     return WINED3D_OK;
943 }
944
945 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
946                                                UINT Width, UINT Height, UINT Depth,
947                                                DWORD Usage,
948                                                WINED3DFORMAT Format, WINED3DPOOL Pool,
949                                                IWineD3DVolume** ppVolume,
950                                                HANDLE* pSharedHandle, IUnknown *parent) {
951
952     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
953     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
954     const PixelFormatDesc *formatDesc  = getFormatDescEntry(Format);
955
956     D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
957
958     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
959           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
960
961     object->currentDesc.Width   = Width;
962     object->currentDesc.Height  = Height;
963     object->currentDesc.Depth   = Depth;
964     object->bytesPerPixel       = formatDesc->bpp;
965
966     /** Note: Volume textures cannot be dxtn, hence no need to check here **/
967     object->lockable            = TRUE;
968     object->locked              = FALSE;
969     memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
970     object->dirty               = TRUE;
971
972     return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
973 }
974
975 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
976                                                     UINT Levels, DWORD Usage,
977                                                     WINED3DFORMAT Format, WINED3DPOOL Pool,
978                                                     IWineD3DCubeTexture **ppCubeTexture,
979                                                     HANDLE *pSharedHandle, IUnknown *parent,
980                                                     D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
981
982     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
983     IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
984     unsigned int             i, j;
985     UINT                     tmpW;
986     HRESULT                  hr;
987     unsigned int pow2EdgeLength  = EdgeLength;
988
989     /* TODO: It should only be possible to create textures for formats 
990              that are reported as supported */
991     if (WINED3DFMT_UNKNOWN >= Format) {
992         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
993         return WINED3DERR_INVALIDCALL;
994     }
995
996     D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
997     D3DINITIALIZEBASETEXTURE(object->baseTexture);
998
999     TRACE("(%p) Create Cube Texture\n", This);
1000
1001     /** Non-power2 support **/
1002
1003     /* Find the nearest pow2 match */
1004     pow2EdgeLength = 1;
1005     while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1006
1007     object->edgeLength           = EdgeLength;
1008     /* TODO: support for native non-power 2 */
1009     /* Precalculated scaling for 'faked' non power of two texture coords */
1010     object->pow2scalingFactor    = ((float)EdgeLength) / ((float)pow2EdgeLength);
1011
1012     /* Calculate levels for mip mapping */
1013     if (Levels == 0) {
1014         object->baseTexture.levels++;
1015         tmpW = EdgeLength;
1016         while (tmpW > 1) {
1017             tmpW = max(1, tmpW >> 1);
1018             object->baseTexture.levels++;
1019         }
1020         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1021     }
1022
1023     /* Generate all the surfaces */
1024     tmpW = EdgeLength;
1025     for (i = 0; i < object->baseTexture.levels; i++) {
1026
1027         /* Create the 6 faces */
1028         for (j = 0; j < 6; j++) {
1029
1030             hr=D3DCB_CreateSurface(This->parent, parent, tmpW, tmpW, Format, Usage, Pool,
1031                                    i /* Level */, &object->surfaces[j][i],pSharedHandle);
1032
1033             if(hr!= WINED3D_OK) {
1034                 /* clean up */
1035                 int k;
1036                 int l;
1037                 for (l = 0; l < j; l++) {
1038                     IWineD3DSurface_Release(object->surfaces[j][i]);
1039                 }
1040                 for (k = 0; k < i; k++) {
1041                     for (l = 0; l < 6; l++) {
1042                     IWineD3DSurface_Release(object->surfaces[l][j]);
1043                     }
1044                 }
1045
1046                 FIXME("(%p) Failed to create surface\n",object);
1047                 HeapFree(GetProcessHeap(),0,object);
1048                 *ppCubeTexture = NULL;
1049                 return hr;
1050             }
1051             IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1052             TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1053         }
1054         tmpW = max(1, tmpW >> 1);
1055     }
1056
1057     TRACE("(%p) : Created Cube Texture %p\n", This, object);
1058     *ppCubeTexture = (IWineD3DCubeTexture *) object;
1059     return WINED3D_OK;
1060 }
1061
1062 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1063     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1064     IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1065     HRESULT hr = WINED3DERR_NOTAVAILABLE;
1066
1067     /* Just a check to see if we support this type of query */
1068     switch(Type) {
1069     case WINED3DQUERYTYPE_OCCLUSION:
1070         TRACE("(%p) occlusion query\n", This);
1071         if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1072             hr = WINED3D_OK;
1073         else
1074             WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1075         break;
1076
1077     case WINED3DQUERYTYPE_EVENT:
1078         if(!(GL_SUPPORT(NV_FENCE) || GL_SUPPORT(APPLE_FENCE) )) {
1079             /* Half-Life 2 needs this query. It does not render the main menu correctly otherwise
1080              * Pretend to support it, faking this query does not do much harm except potentially lowering performance
1081              */
1082             FIXME("(%p) Event query: Unimplemented, but pretending to be supported\n", This);
1083         }
1084         hr = WINED3D_OK;
1085         break;
1086
1087     case WINED3DQUERYTYPE_VCACHE:
1088     case WINED3DQUERYTYPE_RESOURCEMANAGER:
1089     case WINED3DQUERYTYPE_VERTEXSTATS:
1090     case WINED3DQUERYTYPE_TIMESTAMP:
1091     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1092     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1093     case WINED3DQUERYTYPE_PIPELINETIMINGS:
1094     case WINED3DQUERYTYPE_INTERFACETIMINGS:
1095     case WINED3DQUERYTYPE_VERTEXTIMINGS:
1096     case WINED3DQUERYTYPE_PIXELTIMINGS:
1097     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1098     case WINED3DQUERYTYPE_CACHEUTILIZATION:
1099     default:
1100         FIXME("(%p) Unhandled query type %d\n", This, Type);
1101     }
1102     if(NULL == ppQuery || hr != WINED3D_OK) {
1103         return hr;
1104     }
1105
1106     D3DCREATEOBJECTINSTANCE(object, Query)
1107     object->type         = Type;
1108     /* allocated the 'extended' data based on the type of query requested */
1109     switch(Type){
1110     case WINED3DQUERYTYPE_OCCLUSION:
1111         if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1112             TRACE("(%p) Allocating data for an occlusion query\n", This);
1113             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1114             GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1115             break;
1116         }
1117     case WINED3DQUERYTYPE_EVENT:
1118         /* TODO: GL_APPLE_fence */
1119         if(GL_SUPPORT(APPLE_FENCE)) {
1120             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryEventData));
1121             GL_EXTCALL(glGenFencesAPPLE(1, &((WineQueryEventData *)(object->extendedData))->fenceId));
1122             checkGLcall("glGenFencesAPPLE");
1123         } else if(GL_SUPPORT(NV_FENCE)) {
1124             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryEventData));
1125             GL_EXTCALL(glGenFencesNV(1, &((WineQueryEventData *)(object->extendedData))->fenceId));
1126             checkGLcall("glGenFencesNV");
1127         }
1128         break;
1129
1130     case WINED3DQUERYTYPE_VCACHE:
1131     case WINED3DQUERYTYPE_RESOURCEMANAGER:
1132     case WINED3DQUERYTYPE_VERTEXSTATS:
1133     case WINED3DQUERYTYPE_TIMESTAMP:
1134     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1135     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1136     case WINED3DQUERYTYPE_PIPELINETIMINGS:
1137     case WINED3DQUERYTYPE_INTERFACETIMINGS:
1138     case WINED3DQUERYTYPE_VERTEXTIMINGS:
1139     case WINED3DQUERYTYPE_PIXELTIMINGS:
1140     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1141     case WINED3DQUERYTYPE_CACHEUTILIZATION:
1142     default:
1143         object->extendedData = 0;
1144         FIXME("(%p) Unhandled query type %d\n",This , Type);
1145     }
1146     TRACE("(%p) : Created Query %p\n", This, object);
1147     return WINED3D_OK;
1148 }
1149
1150 /*****************************************************************************
1151  * IWineD3DDeviceImpl_SetupFullscreenWindow
1152  *
1153  * Helper function that modifies a HWND's Style and ExStyle for proper
1154  * fullscreen use.
1155  *
1156  * Params:
1157  *  iface: Pointer to the IWineD3DDevice interface
1158  *  window: Window to setup
1159  *
1160  *****************************************************************************/
1161 static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *iface, HWND window) {
1162     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1163
1164     LONG style, exStyle;
1165     /* Don't do anything if an original style is stored.
1166      * That shouldn't happen
1167      */
1168     TRACE("(%p): Setting up window %p for exclusive mode\n", This, window);
1169     if (This->style || This->exStyle) {
1170         ERR("(%p): Want to change the window parameters of HWND %p, but "
1171             "another style is stored for restoration afterwards\n", This, window);
1172     }
1173
1174     /* Get the parameters and save them */
1175     style = GetWindowLongW(window, GWL_STYLE);
1176     exStyle = GetWindowLongW(window, GWL_EXSTYLE);
1177     This->style = style;
1178     This->exStyle = exStyle;
1179
1180     /* Filter out window decorations */
1181     style &= ~WS_CAPTION;
1182     style &= ~WS_THICKFRAME;
1183     exStyle &= ~WS_EX_WINDOWEDGE;
1184     exStyle &= ~WS_EX_CLIENTEDGE;
1185
1186     /* Make sure the window is managed, otherwise we won't get keyboard input */
1187     style |= WS_POPUP | WS_SYSMENU;
1188
1189     TRACE("Old style was %08x,%08x, setting to %08x,%08x\n",
1190           This->style, This->exStyle, style, exStyle);
1191
1192     SetWindowLongW(window, GWL_STYLE, style);
1193     SetWindowLongW(window, GWL_EXSTYLE, exStyle);
1194
1195     /* Inform the window about the update. */
1196     SetWindowPos(window, HWND_TOP, 0, 0,
1197             This->ddraw_width, This->ddraw_height, SWP_FRAMECHANGED);
1198     ShowWindow(window, SW_NORMAL);
1199 }
1200
1201 /*****************************************************************************
1202  * IWineD3DDeviceImpl_RestoreWindow
1203  *
1204  * Helper function that restores a windows' properties when taking it out
1205  * of fullscreen mode
1206  *
1207  * Params:
1208  *  iface: Pointer to the IWineD3DDevice interface
1209  *  window: Window to setup
1210  *
1211  *****************************************************************************/
1212 static void WINAPI IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND window) {
1213     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1214
1215     /* This could be a DDSCL_NORMAL -> DDSCL_NORMAL
1216      * switch, do nothing
1217      */
1218     if (!This->style && !This->exStyle) return;
1219
1220     TRACE("(%p): Restoring window settings of window %p to %08x, %08x\n",
1221           This, window, This->style, This->exStyle);
1222
1223     SetWindowLongW(window, GWL_STYLE, This->style);
1224     SetWindowLongW(window, GWL_EXSTYLE, This->exStyle);
1225
1226     /* Delete the old values */
1227     This->style = 0;
1228     This->exStyle = 0;
1229
1230     /* Inform the window about the update */
1231     SetWindowPos(window, 0 /* InsertAfter, ignored */,
1232                  0, 0, 0, 0, /* Pos, Size, ignored */
1233                  SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
1234 }
1235
1236 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1237 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS*  pPresentationParameters,                                                                   IWineD3DSwapChain** ppSwapChain,
1238                                                             IUnknown* parent,
1239                                                             D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1240                                                             D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1241     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
1242
1243     HDC                     hDc;
1244     IWineD3DSwapChainImpl  *object; /** NOTE: impl ref allowed since this is a create function **/
1245     HRESULT                 hr = WINED3D_OK;
1246     IUnknown               *bufferParent;
1247     Display                *display;
1248
1249     TRACE("(%p) : Created Aditional Swap Chain\n", This);
1250
1251    /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1252    * does a device hold a reference to a swap chain giving them a lifetime of the device
1253    * or does the swap chain notify the device of its destruction.
1254     *******************************/
1255
1256     /* Check the params */
1257     if(pPresentationParameters->BackBufferCount > WINED3DPRESENT_BACK_BUFFER_MAX) {
1258         ERR("App requested %d back buffers, this is not supported for now\n", pPresentationParameters->BackBufferCount);
1259         return WINED3DERR_INVALIDCALL;
1260     } else if (pPresentationParameters->BackBufferCount > 1) {
1261         FIXME("The app requests more than one back buffer, this can't be supported properly. Please configure the application to use double buffering(=1 back buffer) if possible\n");
1262     }
1263
1264     D3DCREATEOBJECTINSTANCE(object, SwapChain)
1265
1266     /*********************
1267     * Lookup the window Handle and the relating X window handle
1268     ********************/
1269
1270     /* Setup hwnd we are using, plus which display this equates to */
1271     object->win_handle = pPresentationParameters->hDeviceWindow;
1272     if (!object->win_handle) {
1273         object->win_handle = This->createParms.hFocusWindow;
1274     }
1275
1276     object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1277     if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1278         ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1279         return WINED3DERR_NOTAVAILABLE;
1280     }
1281     hDc                = GetDC(object->win_handle);
1282     display            = get_display(hDc);
1283     ReleaseDC(object->win_handle, hDc);
1284     TRACE("Using a display of %p %p\n", display, hDc);
1285
1286     if (NULL == display || NULL == hDc) {
1287         WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1288         return WINED3DERR_NOTAVAILABLE;
1289     }
1290
1291     if (object->win == 0) {
1292         WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1293         return WINED3DERR_NOTAVAILABLE;
1294     }
1295
1296     object->orig_width = GetSystemMetrics(SM_CXSCREEN);
1297     object->orig_height = GetSystemMetrics(SM_CYSCREEN);
1298     object->orig_fmt = pixelformat_for_depth(GetDeviceCaps(hDc, BITSPIXEL) * GetDeviceCaps(hDc, PLANES));
1299
1300     /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1301      *  then the corresponding dimension of the client area of the hDeviceWindow
1302      *  (or the focus window, if hDeviceWindow is NULL) is taken.
1303       **********************/
1304
1305     if (pPresentationParameters->Windowed &&
1306         ((pPresentationParameters->BackBufferWidth == 0) ||
1307          (pPresentationParameters->BackBufferHeight == 0))) {
1308
1309         RECT Rect;
1310         GetClientRect(object->win_handle, &Rect);
1311
1312         if (pPresentationParameters->BackBufferWidth == 0) {
1313            pPresentationParameters->BackBufferWidth = Rect.right;
1314            TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
1315         }
1316         if (pPresentationParameters->BackBufferHeight == 0) {
1317            pPresentationParameters->BackBufferHeight = Rect.bottom;
1318            TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
1319         }
1320     }
1321
1322     /* Put the correct figures in the presentation parameters */
1323     TRACE("Copying across presentation parameters\n");
1324     object->presentParms = *pPresentationParameters;
1325
1326     TRACE("calling rendertarget CB\n");
1327     hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1328                              parent,
1329                              object->presentParms.BackBufferWidth,
1330                              object->presentParms.BackBufferHeight,
1331                              object->presentParms.BackBufferFormat,
1332                              object->presentParms.MultiSampleType,
1333                              object->presentParms.MultiSampleQuality,
1334                              TRUE /* Lockable */,
1335                              &object->frontBuffer,
1336                              NULL /* pShared (always null)*/);
1337     if (object->frontBuffer != NULL) {
1338         IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1339     } else {
1340         ERR("Failed to create the front buffer\n");
1341         goto error;
1342     }
1343
1344     /**
1345     * Create an opengl context for the display visual
1346     *  NOTE: the visual is chosen as the window is created and the glcontext cannot
1347     *     use different properties after that point in time. FIXME: How to handle when requested format
1348     *     doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1349     *     it chooses is identical to the one already being used!
1350      **********************************/
1351
1352     /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1353     ENTER_GL();
1354     object->context = CreateContext(This, (IWineD3DSurfaceImpl *) object->frontBuffer, display, object->win);
1355     LEAVE_GL();
1356
1357     if (!object->context) {
1358         ERR("Failed to create a new context\n");
1359         hr = WINED3DERR_NOTAVAILABLE;
1360         goto error;
1361     } else {
1362         TRACE("Context created (HWND=%p, glContext=%p, Window=%ld)\n",
1363                object->win_handle, object->context->glCtx, object->win);
1364     }
1365
1366    /*********************
1367    * Windowed / Fullscreen
1368    *******************/
1369
1370    /**
1371    * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1372    * so we should really check to see if there is a fullscreen swapchain already
1373    * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1374     **************************************/
1375
1376    if (!pPresentationParameters->Windowed) {
1377
1378         DEVMODEW devmode;
1379         HDC      hdc;
1380         int      bpp = 0;
1381         RECT     clip_rc;
1382
1383         /* Get info on the current display setup */
1384         hdc = GetDC(0);
1385         bpp = GetDeviceCaps(hdc, BITSPIXEL);
1386         ReleaseDC(0, hdc);
1387
1388         /* Change the display settings */
1389         memset(&devmode, 0, sizeof(DEVMODEW));
1390         devmode.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1391         devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1392         devmode.dmPelsWidth  = pPresentationParameters->BackBufferWidth;
1393         devmode.dmPelsHeight = pPresentationParameters->BackBufferHeight;
1394         MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1395         ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1396
1397         /* For GetDisplayMode */
1398         This->ddraw_width = devmode.dmPelsWidth;
1399         This->ddraw_height = devmode.dmPelsHeight;
1400         This->ddraw_format = pPresentationParameters->BackBufferFormat;
1401
1402         IWineD3DDevice_SetFullscreen(iface, TRUE);
1403
1404         /* And finally clip mouse to our screen */
1405         SetRect(&clip_rc, 0, 0, devmode.dmPelsWidth, devmode.dmPelsHeight);
1406         ClipCursor(&clip_rc);
1407     }
1408
1409    /*********************
1410    * Create the back, front and stencil buffers
1411    *******************/
1412     if(object->presentParms.BackBufferCount > 0) {
1413         int i;
1414
1415         object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1416         if(!object->backBuffer) {
1417             ERR("Out of memory\n");
1418             hr = E_OUTOFMEMORY;
1419             goto error;
1420         }
1421
1422         for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1423             TRACE("calling rendertarget CB\n");
1424             hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1425                                     parent,
1426                                     object->presentParms.BackBufferWidth,
1427                                     object->presentParms.BackBufferHeight,
1428                                     object->presentParms.BackBufferFormat,
1429                                     object->presentParms.MultiSampleType,
1430                                     object->presentParms.MultiSampleQuality,
1431                                     TRUE /* Lockable */,
1432                                     &object->backBuffer[i],
1433                                     NULL /* pShared (always null)*/);
1434             if(hr == WINED3D_OK && object->backBuffer[i]) {
1435                 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1436             } else {
1437                 ERR("Cannot create new back buffer\n");
1438                 goto error;
1439             }
1440             ENTER_GL();
1441             glDrawBuffer(GL_BACK);
1442             checkGLcall("glDrawBuffer(GL_BACK)");
1443             LEAVE_GL();
1444         }
1445     } else {
1446         object->backBuffer = NULL;
1447
1448         /* Single buffering - draw to front buffer */
1449         ENTER_GL();
1450         glDrawBuffer(GL_FRONT);
1451         checkGLcall("glDrawBuffer(GL_FRONT)");
1452         LEAVE_GL();
1453     }
1454
1455     /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1456     if (pPresentationParameters->EnableAutoDepthStencil && hr == WINED3D_OK) {
1457         TRACE("Creating depth stencil buffer\n");
1458         if (This->depthStencilBuffer == NULL ) {
1459             hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1460                                     parent,
1461                                     object->presentParms.BackBufferWidth,
1462                                     object->presentParms.BackBufferHeight,
1463                                     object->presentParms.AutoDepthStencilFormat,
1464                                     object->presentParms.MultiSampleType,
1465                                     object->presentParms.MultiSampleQuality,
1466                                     FALSE /* FIXME: Discard */,
1467                                     &This->depthStencilBuffer,
1468                                     NULL /* pShared (always null)*/  );
1469             if (This->depthStencilBuffer != NULL)
1470                 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1471         }
1472
1473         /** TODO: A check on width, height and multisample types
1474         *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1475          ****************************/
1476         object->wantsDepthStencilBuffer = TRUE;
1477     } else {
1478         object->wantsDepthStencilBuffer = FALSE;
1479     }
1480
1481     TRACE("Created swapchain %p\n", object);
1482     TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1483     return WINED3D_OK;
1484
1485 error:
1486     if (object->backBuffer) {
1487         int i;
1488         for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1489             if(object->backBuffer[i]) {
1490                 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1491                 IUnknown_Release(bufferParent); /* once for the get parent */
1492                 if (IUnknown_Release(bufferParent) > 0) {
1493                     FIXME("(%p) Something's still holding the back buffer\n",This);
1494                 }
1495             }
1496         }
1497         HeapFree(GetProcessHeap(), 0, object->backBuffer);
1498         object->backBuffer = NULL;
1499     }
1500     if(object->context) {
1501         DestroyContext(This, object->context);
1502     }
1503     if(object->frontBuffer) {
1504         IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1505         IUnknown_Release(bufferParent); /* once for the get parent */
1506         if (IUnknown_Release(bufferParent) > 0) {
1507             FIXME("(%p) Something's still holding the front buffer\n",This);
1508         }
1509     }
1510     if(object) HeapFree(GetProcessHeap(), 0, object);
1511     return hr;
1512 }
1513
1514 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1515 static UINT     WINAPI  IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1516     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1517     TRACE("(%p)\n", This);
1518
1519     return This->NumberOfSwapChains;
1520 }
1521
1522 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1523     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1524     TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1525
1526     if(iSwapChain < This->NumberOfSwapChains) {
1527         *pSwapChain = This->swapchains[iSwapChain];
1528         IWineD3DSwapChain_AddRef(*pSwapChain);
1529         TRACE("(%p) returning %p\n", This, *pSwapChain);
1530         return WINED3D_OK;
1531     } else {
1532         TRACE("Swapchain out of range\n");
1533         *pSwapChain = NULL;
1534         return WINED3DERR_INVALIDCALL;
1535     }
1536 }
1537
1538 /*****
1539  * Vertex Declaration
1540  *****/
1541 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppVertexDeclaration,
1542         IUnknown *parent, const WINED3DVERTEXELEMENT *elements, size_t element_count) {
1543     IWineD3DDeviceImpl            *This   = (IWineD3DDeviceImpl *)iface;
1544     IWineD3DVertexDeclarationImpl *object = NULL;
1545     HRESULT hr = WINED3D_OK;
1546
1547     TRACE("(%p) : directXVersion %u, elements %p, element_count %d, ppDecl=%p\n",
1548             This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, elements, element_count, ppVertexDeclaration);
1549
1550     D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1551     object->allFVF = 0;
1552
1553     hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, elements, element_count);
1554
1555     return hr;
1556 }
1557
1558 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1559 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, IWineD3DVertexDeclaration *vertex_declaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1560     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
1561     IWineD3DVertexShaderImpl *object;  /* NOTE: impl usage is ok, this is a create */
1562     HRESULT hr = WINED3D_OK;
1563     D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1564     object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1565
1566     TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1567
1568     if (vertex_declaration) {
1569         IWineD3DVertexShader_FakeSemantics(*ppVertexShader, vertex_declaration);
1570     }
1571
1572     hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1573
1574     if (WINED3D_OK != hr) {
1575         FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1576         IWineD3DVertexShader_Release(*ppVertexShader);
1577         return WINED3DERR_INVALIDCALL;
1578     }
1579
1580     return WINED3D_OK;
1581 }
1582
1583 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1584     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1585     IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1586     HRESULT hr = WINED3D_OK;
1587
1588     D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
1589     object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1590     hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1591     if (WINED3D_OK == hr) {
1592         TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1593     } else {
1594         WARN("(%p) : Failed to create pixel shader\n", This);
1595     }
1596
1597     return hr;
1598 }
1599
1600 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1601     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1602     IWineD3DPaletteImpl *object;
1603     HRESULT hr;
1604     TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1605
1606     /* Create the new object */
1607     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1608     if(!object) {
1609         ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1610         return E_OUTOFMEMORY;
1611     }
1612
1613     object->lpVtbl = &IWineD3DPalette_Vtbl;
1614     object->ref = 1;
1615     object->Flags = Flags;
1616     object->parent = Parent;
1617     object->wineD3DDevice = This;
1618     object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1619         
1620     object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1621
1622     if(!object->hpal) {
1623         HeapFree( GetProcessHeap(), 0, object);
1624         return E_OUTOFMEMORY;
1625     }
1626
1627     hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1628     if(FAILED(hr)) {
1629         IWineD3DPalette_Release((IWineD3DPalette *) object);
1630         return hr;
1631     }
1632
1633     *Palette = (IWineD3DPalette *) object;
1634
1635     return WINED3D_OK;
1636 }
1637
1638 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1639     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1640     IWineD3DSwapChainImpl *swapchain;
1641     DWORD state;
1642
1643     TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1644     if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1645
1646     /* TODO: Test if OpenGL is compiled in and loaded */
1647
1648     /* Initialize the texture unit mapping to a 1:1 mapping */
1649     for(state = 0; state < MAX_SAMPLERS; state++) {
1650         This->texUnitMap[state] = state;
1651     }
1652     This->oneToOneTexUnitMap = TRUE;
1653
1654     /* Setup the implicit swapchain */
1655     TRACE("Creating implicit swapchain\n");
1656     if (FAILED(D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain)) || !swapchain) {
1657         WARN("Failed to create implicit swapchain\n");
1658         return WINED3DERR_INVALIDCALL;
1659     }
1660
1661     This->NumberOfSwapChains = 1;
1662     This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1663     if(!This->swapchains) {
1664         ERR("Out of memory!\n");
1665         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1666         return E_OUTOFMEMORY;
1667     }
1668     This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1669
1670     if(!This->ddraw_window) IWineD3DDevice_SetHWND(iface, swapchain->win_handle);
1671
1672     if(swapchain->backBuffer && swapchain->backBuffer[0]) {
1673         TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1674         This->render_targets[0] = swapchain->backBuffer[0];
1675         This->lastActiveRenderTarget = swapchain->backBuffer[0];
1676     }
1677     else {
1678         TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1679         This->render_targets[0] = swapchain->frontBuffer;
1680         This->lastActiveRenderTarget = swapchain->frontBuffer;
1681     }
1682     IWineD3DSurface_AddRef(This->render_targets[0]);
1683     This->activeContext = swapchain->context;
1684
1685     /* Depth Stencil support */
1686     This->stencilBufferTarget = This->depthStencilBuffer;
1687     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
1688         set_depth_stencil_fbo(iface, This->depthStencilBuffer);
1689     }
1690     if (NULL != This->stencilBufferTarget) {
1691         IWineD3DSurface_AddRef(This->stencilBufferTarget);
1692     }
1693
1694     /* Set up some starting GL setup */
1695     ENTER_GL();
1696     /*
1697     * Initialize openGL extension related variables
1698     *  with Default values
1699     */
1700
1701     ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->context->display);
1702     /* Setup all the devices defaults */
1703     IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1704 #if 0
1705     IWineD3DImpl_CheckGraphicsMemory();
1706 #endif
1707
1708     { /* Set a default viewport */
1709         WINED3DVIEWPORT vp;
1710         vp.X      = 0;
1711         vp.Y      = 0;
1712         vp.Width  = pPresentationParameters->BackBufferWidth;
1713         vp.Height = pPresentationParameters->BackBufferHeight;
1714         vp.MinZ   = 0.0f;
1715         vp.MaxZ   = 1.0f;
1716         IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1717     }
1718
1719     /* Initialize the current view state */
1720     This->view_ident = 1;
1721     This->contexts[0]->last_was_rhw = 0;
1722     glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1723     checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
1724
1725     switch(wined3d_settings.offscreen_rendering_mode) {
1726         case ORM_FBO:
1727         case ORM_PBUFFER:
1728             This->offscreenBuffer = GL_BACK;
1729             break;
1730
1731         case ORM_BACKBUFFER:
1732         {
1733             if(GL_LIMITS(aux_buffers) > 0) {
1734                 TRACE("Using auxilliary buffer for offscreen rendering\n");
1735                 This->offscreenBuffer = GL_AUX0;
1736             } else {
1737                 TRACE("Using back buffer for offscreen rendering\n");
1738                 This->offscreenBuffer = GL_BACK;
1739             }
1740         }
1741     }
1742
1743     TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1744     LEAVE_GL();
1745
1746     /* Clear the screen */
1747     IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL,
1748                           WINED3DCLEAR_TARGET | pPresentationParameters->EnableAutoDepthStencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0,
1749                           0x00, 1.0, 0);
1750
1751     This->d3d_initialized = TRUE;
1752     return WINED3D_OK;
1753 }
1754
1755 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
1756     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1757     int sampler;
1758     uint i;
1759     TRACE("(%p)\n", This);
1760
1761     if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1762
1763     /* Delete the pbuffer context if there is any */
1764     if(This->pbufferContext) DestroyContext(This, This->pbufferContext);
1765
1766     /* Delete the mouse cursor texture */
1767     if(This->cursorTexture) {
1768         ENTER_GL();
1769         glDeleteTextures(1, &This->cursorTexture);
1770         LEAVE_GL();
1771         This->cursorTexture = 0;
1772     }
1773
1774     for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
1775         IWineD3DDevice_SetTexture(iface, sampler, NULL);
1776     }
1777
1778     /* Release the buffers (with sanity checks)*/
1779     TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1780     if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1781         if(This->depthStencilBuffer != This->stencilBufferTarget)
1782             FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1783     }
1784     This->stencilBufferTarget = NULL;
1785
1786     TRACE("Releasing the render target at %p\n", This->render_targets[0]);
1787     if(IWineD3DSurface_Release(This->render_targets[0]) >0){
1788           /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1789     }
1790     TRACE("Setting rendertarget to NULL\n");
1791     This->render_targets[0] = NULL;
1792
1793     if (This->depthStencilBuffer) {
1794         if(D3DCB_DestroyDepthStencilSurface(This->depthStencilBuffer) > 0) {
1795             FIXME("(%p) Something's still holding the depthStencilBuffer\n", This);
1796         }
1797         This->depthStencilBuffer = NULL;
1798     }
1799
1800     for(i=0; i < This->NumberOfSwapChains; i++) {
1801         TRACE("Releasing the implicit swapchain %d\n", i);
1802         if (D3DCB_DestroySwapChain(This->swapchains[i])  > 0) {
1803             FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1804         }
1805     }
1806
1807     HeapFree(GetProcessHeap(), 0, This->swapchains);
1808     This->swapchains = NULL;
1809     This->NumberOfSwapChains = 0;
1810
1811     This->d3d_initialized = FALSE;
1812     return WINED3D_OK;
1813 }
1814
1815 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
1816     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1817     TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
1818
1819     /* Setup the window for fullscreen mode */
1820     if(fullscreen && !This->ddraw_fullscreen) {
1821         IWineD3DDeviceImpl_SetupFullscreenWindow(iface, This->ddraw_window);
1822     } else if(!fullscreen && This->ddraw_fullscreen) {
1823         IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
1824     }
1825
1826     /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
1827      * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
1828      * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
1829      * separately.
1830      */
1831     This->ddraw_fullscreen = fullscreen;
1832 }
1833
1834 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1835     DEVMODEW devmode;
1836     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1837     LONG ret;
1838     const PixelFormatDesc *formatDesc  = getFormatDescEntry(pMode->Format);
1839     RECT clip_rc;
1840
1841     TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1842
1843     /* Resize the screen even without a window:
1844      * The app could have unset it with SetCooperativeLevel, but not called
1845      * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1846      * but we don't have any hwnd
1847      */
1848
1849     devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1850     devmode.dmBitsPerPel = formatDesc->bpp * 8;
1851     if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
1852     devmode.dmPelsWidth  = pMode->Width;
1853     devmode.dmPelsHeight = pMode->Height;
1854
1855     devmode.dmDisplayFrequency = pMode->RefreshRate;
1856     if (pMode->RefreshRate != 0)  {
1857         devmode.dmFields |= DM_DISPLAYFREQUENCY;
1858     }
1859
1860     /* Only change the mode if necessary */
1861     if( (This->ddraw_width == pMode->Width) &&
1862         (This->ddraw_height == pMode->Height) &&
1863         (This->ddraw_format == pMode->Format) &&
1864         (pMode->RefreshRate == 0) ) {
1865         return WINED3D_OK;
1866     }
1867
1868     ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
1869     if (ret != DISP_CHANGE_SUCCESSFUL) {
1870         if(devmode.dmDisplayFrequency != 0) {
1871             WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
1872             devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
1873             devmode.dmDisplayFrequency = 0;
1874             ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
1875         }
1876         if(ret != DISP_CHANGE_SUCCESSFUL) {
1877             return DDERR_INVALIDMODE;
1878         }
1879     }
1880
1881     /* Store the new values */
1882     This->ddraw_width = pMode->Width;
1883     This->ddraw_height = pMode->Height;
1884     This->ddraw_format = pMode->Format;
1885
1886     /* Only do this with a window of course */
1887     if(This->ddraw_window)
1888       MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
1889
1890     /* And finally clip mouse to our screen */
1891     SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height);
1892     ClipCursor(&clip_rc);
1893
1894     return WINED3D_OK;
1895 }
1896
1897 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1898    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1899    *ppD3D= This->wineD3D;
1900    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
1901    IWineD3D_AddRef(*ppD3D);
1902    return WINED3D_OK;
1903 }
1904
1905 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1906     /** NOTE: There's a probably  a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
1907     * into the video ram as possible and seeing how many fit
1908     * you can also get the correct initial value from nvidia and ATI's driver via X
1909     * texture memory is video memory + AGP memory
1910     *******************/
1911     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1912     static BOOL showfixmes = TRUE;
1913     if (showfixmes) {
1914         FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
1915          (wined3d_settings.emulated_textureram/(1024*1024)),
1916          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1917          showfixmes = FALSE;
1918     }
1919     TRACE("(%p) : simulating %dMB, returning %dMB left\n",  This,
1920          (wined3d_settings.emulated_textureram/(1024*1024)),
1921          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1922     /* return simulated texture memory left */
1923     return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1924 }
1925
1926
1927
1928 /*****
1929  * Get / Set FVF
1930  *****/
1931 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1932     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1933
1934     /* Update the current state block */
1935     This->updateStateBlock->changed.fvf      = TRUE;
1936     This->updateStateBlock->set.fvf          = TRUE;
1937
1938     if(This->updateStateBlock->fvf == fvf) {
1939         TRACE("Application is setting the old fvf over, nothing to do\n");
1940         return WINED3D_OK;
1941     }
1942
1943     This->updateStateBlock->fvf              = fvf;
1944     TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
1945     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
1946     return WINED3D_OK;
1947 }
1948
1949
1950 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1951     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1952     TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
1953     *pfvf = This->stateBlock->fvf;
1954     return WINED3D_OK;
1955 }
1956
1957 /*****
1958  * Get / Set Stream Source
1959  *****/
1960 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1961         IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
1962     IWineD3DVertexBuffer     *oldSrc;
1963
1964     if (StreamNumber >= MAX_STREAMS) {
1965         WARN("Stream out of range %d\n", StreamNumber);
1966         return WINED3DERR_INVALIDCALL;
1967     }
1968
1969     oldSrc = This->stateBlock->streamSource[StreamNumber];
1970     TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1971
1972     This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1973     This->updateStateBlock->set.streamSource[StreamNumber]     = TRUE;
1974
1975     if(oldSrc == pStreamData &&
1976        This->updateStateBlock->streamStride[StreamNumber] == Stride &&
1977        This->updateStateBlock->streamOffset[StreamNumber] == OffsetInBytes) {
1978        TRACE("Application is setting the old values over, nothing to do\n");
1979        return WINED3D_OK;
1980     }
1981
1982     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
1983     if (pStreamData) {
1984         This->updateStateBlock->streamStride[StreamNumber]     = Stride;
1985         This->updateStateBlock->streamOffset[StreamNumber]     = OffsetInBytes;
1986     }
1987
1988     /* Handle recording of state blocks */
1989     if (This->isRecordingState) {
1990         TRACE("Recording... not performing anything\n");
1991         return WINED3D_OK;
1992     }
1993
1994     /* Need to do a getParent and pass the reffs up */
1995     /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1996     which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1997     so for now, just count internally   */
1998     if (pStreamData != NULL) {
1999         IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2000         InterlockedIncrement(&vbImpl->bindCount);
2001     }
2002     if (oldSrc != NULL) {
2003         InterlockedDecrement(&((IWineD3DVertexBufferImpl *) oldSrc)->bindCount);
2004     }
2005
2006     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2007
2008     return WINED3D_OK;
2009 }
2010
2011 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2012     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2013
2014     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2015            This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2016
2017     if (StreamNumber >= MAX_STREAMS) {
2018         WARN("Stream out of range %d\n", StreamNumber);
2019         return WINED3DERR_INVALIDCALL;
2020     }
2021     *pStream = This->stateBlock->streamSource[StreamNumber];
2022     *pStride = This->stateBlock->streamStride[StreamNumber];
2023     if (pOffset) {
2024         *pOffset = This->stateBlock->streamOffset[StreamNumber];
2025     }
2026
2027     if (*pStream != NULL) {
2028         IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2029     }
2030     return WINED3D_OK;
2031 }
2032
2033 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
2034     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2035     UINT oldFlags = This->updateStateBlock->streamFlags[StreamNumber];
2036     UINT oldFreq = This->updateStateBlock->streamFreq[StreamNumber];
2037
2038     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2039     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA  | WINED3DSTREAMSOURCE_INDEXEDDATA );
2040
2041     This->updateStateBlock->changed.streamFreq[StreamNumber]  = TRUE;
2042     This->updateStateBlock->set.streamFreq[StreamNumber]      = TRUE;
2043     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
2044
2045     if(This->updateStateBlock->streamFreq[StreamNumber] != oldFreq ||
2046        This->updateStateBlock->streamFlags[StreamNumber] != oldFlags) {
2047         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2048     }
2049
2050     return WINED3D_OK;
2051 }
2052
2053 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
2054     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2055
2056     TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2057     *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2058
2059     TRACE("(%p) : returning %d\n", This, *Divider);
2060
2061     return WINED3D_OK;
2062 }
2063
2064 /*****
2065  * Get / Set & Multiply Transform
2066  *****/
2067 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2068     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2069
2070     /* Most of this routine, comments included copied from ddraw tree initially: */
2071     TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2072
2073     /* Handle recording of state blocks */
2074     if (This->isRecordingState) {
2075         TRACE("Recording... not performing anything\n");
2076         This->updateStateBlock->changed.transform[d3dts] = TRUE;
2077         This->updateStateBlock->set.transform[d3dts]     = TRUE;
2078         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2079         return WINED3D_OK;
2080     }
2081
2082     /*
2083      * If the new matrix is the same as the current one,
2084      * we cut off any further processing. this seems to be a reasonable
2085      * optimization because as was noticed, some apps (warcraft3 for example)
2086      * tend towards setting the same matrix repeatedly for some reason.
2087      *
2088      * From here on we assume that the new matrix is different, wherever it matters.
2089      */
2090     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2091         TRACE("The app is setting the same matrix over again\n");
2092         return WINED3D_OK;
2093     } else {
2094         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2095     }
2096
2097     /*
2098        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2099        where ViewMat = Camera space, WorldMat = world space.
2100
2101        In OpenGL, camera and world space is combined into GL_MODELVIEW
2102        matrix.  The Projection matrix stay projection matrix.
2103      */
2104
2105     /* Capture the times we can just ignore the change for now */
2106     if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2107         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2108         /* Handled by the state manager */
2109     }
2110
2111     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2112     return WINED3D_OK;
2113
2114 }
2115 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2116     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2117     TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2118     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2119     return WINED3D_OK;
2120 }
2121
2122 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2123     WINED3DMATRIX *mat = NULL;
2124     WINED3DMATRIX temp;
2125
2126     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2127      * below means it will be recorded in a state block change, but it
2128      * works regardless where it is recorded.
2129      * If this is found to be wrong, change to StateBlock.
2130      */
2131     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2132     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2133
2134     if (State < HIGHEST_TRANSFORMSTATE)
2135     {
2136         mat = &This->updateStateBlock->transforms[State];
2137     } else {
2138         FIXME("Unhandled transform state!!\n");
2139     }
2140
2141     multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2142
2143     /* Apply change via set transform - will reapply to eg. lights this way */
2144     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2145 }
2146
2147 /*****
2148  * Get / Set Light
2149  *****/
2150 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2151    you can reference any indexes you want as long as that number max are enabled at any
2152    one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2153    However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2154    but when recording, just build a chain pretty much of commands to be replayed.                  */
2155
2156 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2157     float rho;
2158     PLIGHTINFOEL *object = NULL;
2159     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2160     struct list *e;
2161
2162     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2163     TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This, Index, pLight, Hi);
2164
2165     /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2166      * the gl driver.
2167      */
2168     if(!pLight) {
2169         WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2170         return WINED3DERR_INVALIDCALL;
2171     }
2172
2173     switch(pLight->Type) {
2174         case WINED3DLIGHT_POINT:
2175         case WINED3DLIGHT_SPOT:
2176         case WINED3DLIGHT_PARALLELPOINT:
2177         case WINED3DLIGHT_GLSPOT:
2178             /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2179              * most wanted
2180              */
2181             if(pLight->Attenuation0 < 0.0 || pLight->Attenuation1 < 0.0 || pLight->Attenuation2 < 0.0) {
2182                 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2183                 return WINED3DERR_INVALIDCALL;
2184             }
2185             break;
2186
2187         case WINED3DLIGHT_DIRECTIONAL:
2188             /* Ignores attenuation */
2189             break;
2190
2191         default:
2192         WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2193         return WINED3DERR_INVALIDCALL;
2194     }
2195
2196     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2197         object = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2198         if(object->OriginalIndex == Index) break;
2199         object = NULL;
2200     }
2201
2202     if(!object) {
2203         TRACE("Adding new light\n");
2204         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2205         if(!object) {
2206             ERR("Out of memory error when allocating a light\n");
2207             return E_OUTOFMEMORY;
2208         }
2209         list_add_head(&This->updateStateBlock->lightMap[Hi], &object->entry);
2210         object->glIndex = -1;
2211         object->OriginalIndex = Index;
2212         object->changed = TRUE;
2213     }
2214
2215     /* Initialize the object */
2216     TRACE("Light %d setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
2217           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2218           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2219           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2220     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2221           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2222     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2223
2224     /* Save away the information */
2225     memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2226
2227     switch (pLight->Type) {
2228     case WINED3DLIGHT_POINT:
2229         /* Position */
2230         object->lightPosn[0] = pLight->Position.x;
2231         object->lightPosn[1] = pLight->Position.y;
2232         object->lightPosn[2] = pLight->Position.z;
2233         object->lightPosn[3] = 1.0f;
2234         object->cutoff = 180.0f;
2235         /* FIXME: Range */
2236         break;
2237
2238     case WINED3DLIGHT_DIRECTIONAL:
2239         /* Direction */
2240         object->lightPosn[0] = -pLight->Direction.x;
2241         object->lightPosn[1] = -pLight->Direction.y;
2242         object->lightPosn[2] = -pLight->Direction.z;
2243         object->lightPosn[3] = 0.0;
2244         object->exponent     = 0.0f;
2245         object->cutoff       = 180.0f;
2246         break;
2247
2248     case WINED3DLIGHT_SPOT:
2249         /* Position */
2250         object->lightPosn[0] = pLight->Position.x;
2251         object->lightPosn[1] = pLight->Position.y;
2252         object->lightPosn[2] = pLight->Position.z;
2253         object->lightPosn[3] = 1.0;
2254
2255         /* Direction */
2256         object->lightDirn[0] = pLight->Direction.x;
2257         object->lightDirn[1] = pLight->Direction.y;
2258         object->lightDirn[2] = pLight->Direction.z;
2259         object->lightDirn[3] = 1.0;
2260
2261         /*
2262          * opengl-ish and d3d-ish spot lights use too different models for the
2263          * light "intensity" as a function of the angle towards the main light direction,
2264          * so we only can approximate very roughly.
2265          * however spot lights are rather rarely used in games (if ever used at all).
2266          * furthermore if still used, probably nobody pays attention to such details.
2267          */
2268         if (pLight->Falloff == 0) {
2269             rho = 6.28f;
2270         } else {
2271             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2272         }
2273         if (rho < 0.0001) rho = 0.0001f;
2274         object->exponent = -0.3/log(cos(rho/2));
2275         if (object->exponent > 128.0) {
2276                 object->exponent = 128.0;
2277         }
2278         object->cutoff = pLight->Phi*90/M_PI;
2279
2280         /* FIXME: Range */
2281         break;
2282
2283     default:
2284         FIXME("Unrecognized light type %d\n", pLight->Type);
2285     }
2286
2287     /* Update the live definitions if the light is currently assigned a glIndex */
2288     if (object->glIndex != -1 && !This->isRecordingState) {
2289         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(object->glIndex));
2290     }
2291     return WINED3D_OK;
2292 }
2293
2294 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2295     PLIGHTINFOEL *lightInfo = NULL;
2296     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2297     DWORD Hi = LIGHTMAP_HASHFUNC(Index);
2298     struct list *e;
2299     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2300
2301     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2302         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2303         if(lightInfo->OriginalIndex == Index) break;
2304         lightInfo = NULL;
2305     }
2306
2307     if (lightInfo == NULL) {
2308         TRACE("Light information requested but light not defined\n");
2309         return WINED3DERR_INVALIDCALL;
2310     }
2311
2312     memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2313     return WINED3D_OK;
2314 }
2315
2316 /*****
2317  * Get / Set Light Enable
2318  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2319  *****/
2320 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2321     PLIGHTINFOEL *lightInfo = NULL;
2322     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2323     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2324     struct list *e;
2325     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2326
2327     /* Tests show true = 128...not clear why */
2328     Enable = Enable? 128: 0;
2329
2330     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2331         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2332         if(lightInfo->OriginalIndex == Index) break;
2333         lightInfo = NULL;
2334     }
2335     TRACE("Found light: %p\n", lightInfo);
2336
2337     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2338     if (lightInfo == NULL) {
2339
2340         TRACE("Light enabled requested but light not defined, so defining one!\n");
2341         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2342
2343         /* Search for it again! Should be fairly quick as near head of list */
2344         LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2345             lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2346             if(lightInfo->OriginalIndex == Index) break;
2347             lightInfo = NULL;
2348         }
2349         if (lightInfo == NULL) {
2350             FIXME("Adding default lights has failed dismally\n");
2351             return WINED3DERR_INVALIDCALL;
2352         }
2353     }
2354
2355     lightInfo->enabledChanged = TRUE;
2356     if(!Enable) {
2357         if(lightInfo->glIndex != -1) {
2358             if(!This->isRecordingState) {
2359                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(lightInfo->glIndex));
2360             }
2361
2362             This->stateBlock->activeLights[lightInfo->glIndex] = NULL;
2363             lightInfo->glIndex = -1;
2364         } else {
2365             TRACE("Light already disabled, nothing to do\n");
2366         }
2367     } else {
2368         if (lightInfo->glIndex != -1) {
2369             /* nop */
2370             TRACE("Nothing to do as light was enabled\n");
2371         } else {
2372             int i;
2373             /* Find a free gl light */
2374             for(i = 0; i < This->maxConcurrentLights; i++) {
2375                 if(This->stateBlock->activeLights[i] == NULL) {
2376                     This->stateBlock->activeLights[i] = lightInfo;
2377                     lightInfo->glIndex = i;
2378                     break;
2379                 }
2380             }
2381             if(lightInfo->glIndex == -1) {
2382                 ERR("Too many concurrently active lights\n");
2383                 return WINED3DERR_INVALIDCALL;
2384             }
2385
2386             /* i == lightInfo->glIndex */
2387             if(!This->isRecordingState) {
2388                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(i));
2389             }
2390         }
2391     }
2392
2393     return WINED3D_OK;
2394 }
2395
2396 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2397
2398     PLIGHTINFOEL *lightInfo = NULL;
2399     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2400     struct list *e;
2401     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2402     TRACE("(%p) : for idx(%d)\n", This, Index);
2403
2404     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2405         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2406         if(lightInfo->OriginalIndex == Index) break;
2407         lightInfo = NULL;
2408     }
2409
2410     if (lightInfo == NULL) {
2411         TRACE("Light enabled state requested but light not defined\n");
2412         return WINED3DERR_INVALIDCALL;
2413     }
2414     /* true is 128 according to SetLightEnable */
2415     *pEnable = lightInfo->glIndex != -1 ? 128 : 0;
2416     return WINED3D_OK;
2417 }
2418
2419 /*****
2420  * Get / Set Clip Planes
2421  *****/
2422 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2423     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2424     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
2425
2426     /* Validate Index */
2427     if (Index >= GL_LIMITS(clipplanes)) {
2428         TRACE("Application has requested clipplane this device doesn't support\n");
2429         return WINED3DERR_INVALIDCALL;
2430     }
2431
2432     This->updateStateBlock->changed.clipplane[Index] = TRUE;
2433     This->updateStateBlock->set.clipplane[Index] = TRUE;
2434
2435     if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] &&
2436        This->updateStateBlock->clipplane[Index][1] == pPlane[1] &&
2437        This->updateStateBlock->clipplane[Index][2] == pPlane[2] &&
2438        This->updateStateBlock->clipplane[Index][3] == pPlane[3]) {
2439         TRACE("Application is setting old values over, nothing to do\n");
2440         return WINED3D_OK;
2441     }
2442
2443     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2444     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2445     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2446     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2447
2448     /* Handle recording of state blocks */
2449     if (This->isRecordingState) {
2450         TRACE("Recording... not performing anything\n");
2451         return WINED3D_OK;
2452     }
2453
2454     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_CLIPPLANE(Index));
2455
2456     return WINED3D_OK;
2457 }
2458
2459 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2460     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2461     TRACE("(%p) : for idx %d\n", This, Index);
2462
2463     /* Validate Index */
2464     if (Index >= GL_LIMITS(clipplanes)) {
2465         TRACE("Application has requested clipplane this device doesn't support\n");
2466         return WINED3DERR_INVALIDCALL;
2467     }
2468
2469     pPlane[0] = This->stateBlock->clipplane[Index][0];
2470     pPlane[1] = This->stateBlock->clipplane[Index][1];
2471     pPlane[2] = This->stateBlock->clipplane[Index][2];
2472     pPlane[3] = This->stateBlock->clipplane[Index][3];
2473     return WINED3D_OK;
2474 }
2475
2476 /*****
2477  * Get / Set Clip Plane Status
2478  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2479  *****/
2480 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2481     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2482     FIXME("(%p) : stub\n", This);
2483     if (NULL == pClipStatus) {
2484       return WINED3DERR_INVALIDCALL;
2485     }
2486     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2487     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2488     return WINED3D_OK;
2489 }
2490
2491 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2492     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2493     FIXME("(%p) : stub\n", This);
2494     if (NULL == pClipStatus) {
2495       return WINED3DERR_INVALIDCALL;
2496     }
2497     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2498     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2499     return WINED3D_OK;
2500 }
2501
2502 /*****
2503  * Get / Set Material
2504  *****/
2505 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2506     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2507
2508     This->updateStateBlock->changed.material = TRUE;
2509     This->updateStateBlock->set.material = TRUE;
2510     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2511
2512     /* Handle recording of state blocks */
2513     if (This->isRecordingState) {
2514         TRACE("Recording... not performing anything\n");
2515         return WINED3D_OK;
2516     }
2517
2518     ENTER_GL();
2519     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2520         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2521     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2522         pMaterial->Ambient.b, pMaterial->Ambient.a);
2523     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2524         pMaterial->Specular.b, pMaterial->Specular.a);
2525     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2526         pMaterial->Emissive.b, pMaterial->Emissive.a);
2527     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2528
2529     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2530     checkGLcall("glMaterialfv(GL_AMBIENT)");
2531     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2532     checkGLcall("glMaterialfv(GL_DIFFUSE)");
2533
2534     /* Only change material color if specular is enabled, otherwise it is set to black */
2535     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2536        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2537        checkGLcall("glMaterialfv(GL_SPECULAR");
2538     } else {
2539        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2540        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2541        checkGLcall("glMaterialfv(GL_SPECULAR");
2542     }
2543     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2544     checkGLcall("glMaterialfv(GL_EMISSION)");
2545     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2546     checkGLcall("glMaterialf(GL_SHININESS");
2547
2548     LEAVE_GL();
2549     return WINED3D_OK;
2550 }
2551
2552 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2553     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2554     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2555     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2556         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2557     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2558         pMaterial->Ambient.b, pMaterial->Ambient.a);
2559     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2560         pMaterial->Specular.b, pMaterial->Specular.a);
2561     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2562         pMaterial->Emissive.b, pMaterial->Emissive.a);
2563     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2564
2565     return WINED3D_OK;
2566 }
2567
2568 /*****
2569  * Get / Set Indices
2570  *****/
2571 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2572                                              UINT BaseVertexIndex) {
2573     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
2574     IWineD3DIndexBuffer *oldIdxs;
2575     UINT oldBaseIndex = This->updateStateBlock->baseVertexIndex;
2576
2577     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2578     oldIdxs = This->updateStateBlock->pIndexData;
2579
2580     This->updateStateBlock->changed.indices = TRUE;
2581     This->updateStateBlock->set.indices = TRUE;
2582     This->updateStateBlock->pIndexData = pIndexData;
2583     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2584
2585     /* Handle recording of state blocks */
2586     if (This->isRecordingState) {
2587         TRACE("Recording... not performing anything\n");
2588         return WINED3D_OK;
2589     }
2590
2591     /* The base vertex index affects the stream sources, while
2592      * The index buffer is a seperate index buffer state
2593      */
2594     if(BaseVertexIndex != oldBaseIndex) {
2595         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2596     }
2597     if(oldIdxs != pIndexData) {
2598         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
2599     }
2600     return WINED3D_OK;
2601 }
2602
2603 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2604     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2605
2606     *ppIndexData = This->stateBlock->pIndexData;
2607
2608     /* up ref count on ppindexdata */
2609     if (*ppIndexData) {
2610         IWineD3DIndexBuffer_AddRef(*ppIndexData);
2611         *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2612         TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2613     }else{
2614         TRACE("(%p) No index data set\n", This);
2615     }
2616     TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2617
2618     return WINED3D_OK;
2619 }
2620
2621 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
2622 static HRESULT WINAPI IWineD3DDeviceImpl_SetBasevertexIndex(IWineD3DDevice *iface, UINT BaseIndex) {
2623     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2624     TRACE("(%p)->(%d)\n", This, BaseIndex);
2625
2626     if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
2627         TRACE("Application is setting the old value over, nothing to do\n");
2628         return WINED3D_OK;
2629     }
2630
2631     This->updateStateBlock->baseVertexIndex = BaseIndex;
2632
2633     if (This->isRecordingState) {
2634         TRACE("Recording... not performing anything\n");
2635         return WINED3D_OK;
2636     }
2637     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2638     return WINED3D_OK;
2639 }
2640
2641 /*****
2642  * Get / Set Viewports
2643  *****/
2644 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2645     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2646
2647     TRACE("(%p)\n", This);
2648     This->updateStateBlock->changed.viewport = TRUE;
2649     This->updateStateBlock->set.viewport = TRUE;
2650     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2651
2652     /* Handle recording of state blocks */
2653     if (This->isRecordingState) {
2654         TRACE("Recording... not performing anything\n");
2655         return WINED3D_OK;
2656     }
2657
2658     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
2659           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2660
2661     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
2662     return WINED3D_OK;
2663
2664 }
2665
2666 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2667     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2668     TRACE("(%p)\n", This);
2669     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2670     return WINED3D_OK;
2671 }
2672
2673 /*****
2674  * Get / Set Render States
2675  * TODO: Verify against dx9 definitions
2676  *****/
2677 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
2678
2679     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
2680     DWORD oldValue = This->stateBlock->renderState[State];
2681
2682     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
2683
2684     This->updateStateBlock->changed.renderState[State] = TRUE;
2685     This->updateStateBlock->set.renderState[State] = TRUE;
2686     This->updateStateBlock->renderState[State] = Value;
2687
2688     /* Handle recording of state blocks */
2689     if (This->isRecordingState) {
2690         TRACE("Recording... not performing anything\n");
2691         return WINED3D_OK;
2692     }
2693
2694     /* Compared here and not before the assignment to allow proper stateblock recording */
2695     if(Value == oldValue) {
2696         TRACE("Application is setting the old value over, nothing to do\n");
2697     } else {
2698         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
2699     }
2700
2701     return WINED3D_OK;
2702 }
2703
2704 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
2705     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2706     TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
2707     *pValue = This->stateBlock->renderState[State];
2708     return WINED3D_OK;
2709 }
2710
2711 /*****
2712  * Get / Set Sampler States
2713  * TODO: Verify against dx9 definitions
2714  *****/
2715
2716 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
2717     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2718     DWORD oldValue = This->stateBlock->samplerState[Sampler][Type];
2719
2720     /**
2721     * SetSampler is designed to allow for more than the standard up to 8 textures
2722     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
2723     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
2724     *
2725     * http://developer.nvidia.com/object/General_FAQ.html#t6
2726     *
2727     * There are two new settings for GForce
2728     * the sampler one:
2729     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
2730     * and the texture one:
2731     * GL_MAX_TEXTURE_COORDS_ARB.
2732     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
2733      ******************/
2734
2735     TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
2736         debug_d3dsamplerstate(Type), Type, Value);
2737     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
2738     This->updateStateBlock->set.samplerState[Sampler][Type]     = Value;
2739     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
2740
2741     /* Handle recording of state blocks */
2742     if (This->isRecordingState) {
2743         TRACE("Recording... not performing anything\n");
2744         return WINED3D_OK;
2745     }
2746
2747     if(oldValue == Value) {
2748         TRACE("Application is setting the old value over, nothing to do\n");
2749         return WINED3D_OK;
2750     }
2751
2752     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
2753
2754     return WINED3D_OK;
2755 }
2756
2757 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
2758     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2759     *Value = This->stateBlock->samplerState[Sampler][Type];
2760     TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
2761
2762     return WINED3D_OK;
2763 }
2764
2765 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
2766     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2767
2768     This->updateStateBlock->set.scissorRect = TRUE;
2769     This->updateStateBlock->changed.scissorRect = TRUE;
2770     if(EqualRect(&This->updateStateBlock->scissorRect, pRect)) {
2771         TRACE("App is setting the old scissor rectangle over, nothing to do\n");
2772         return WINED3D_OK;
2773     }
2774     CopyRect(&This->updateStateBlock->scissorRect, pRect);
2775
2776     if(This->isRecordingState) {
2777         TRACE("Recording... not performing anything\n");
2778         return WINED3D_OK;
2779     }
2780
2781     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
2782
2783     return WINED3D_OK;
2784 }
2785
2786 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
2787     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2788
2789     memcpy(pRect, &This->updateStateBlock->scissorRect, sizeof(pRect));
2790     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2791     return WINED3D_OK;
2792 }
2793
2794 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
2795     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2796     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
2797
2798     TRACE("(%p) : pDecl=%p\n", This, pDecl);
2799
2800     This->updateStateBlock->vertexDecl = pDecl;
2801     This->updateStateBlock->changed.vertexDecl = TRUE;
2802     This->updateStateBlock->set.vertexDecl = TRUE;
2803
2804     if (This->isRecordingState) {
2805         TRACE("Recording... not performing anything\n");
2806         return WINED3D_OK;
2807     } else if(pDecl == oldDecl) {
2808         /* Checked after the assignment to allow proper stateblock recording */
2809         TRACE("Application is setting the old declaration over, nothing to do\n");
2810         return WINED3D_OK;
2811     }
2812
2813     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
2814     return WINED3D_OK;
2815 }
2816
2817 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
2818     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2819
2820     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
2821
2822     *ppDecl = This->stateBlock->vertexDecl;
2823     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
2824     return WINED3D_OK;
2825 }
2826
2827 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
2828     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
2829     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
2830
2831     This->updateStateBlock->vertexShader         = pShader;
2832     This->updateStateBlock->changed.vertexShader = TRUE;
2833     This->updateStateBlock->set.vertexShader     = TRUE;
2834
2835     if (This->isRecordingState) {
2836         TRACE("Recording... not performing anything\n");
2837         return WINED3D_OK;
2838     } else if(oldShader == pShader) {
2839         /* Checked here to allow proper stateblock recording */
2840         TRACE("App is setting the old shader over, nothing to do\n");
2841         return WINED3D_OK;
2842     }
2843
2844     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
2845
2846     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
2847
2848     return WINED3D_OK;
2849 }
2850
2851 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
2852     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2853
2854     if (NULL == ppShader) {
2855         return WINED3DERR_INVALIDCALL;
2856     }
2857     *ppShader = This->stateBlock->vertexShader;
2858     if( NULL != *ppShader)
2859         IWineD3DVertexShader_AddRef(*ppShader);
2860
2861     TRACE("(%p) : returning %p\n", This, *ppShader);
2862     return WINED3D_OK;
2863 }
2864
2865 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
2866     IWineD3DDevice *iface,
2867     UINT start,
2868     CONST BOOL *srcData,
2869     UINT count) {
2870
2871     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2872     int i, cnt = min(count, MAX_CONST_B - start);
2873
2874     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2875             iface, srcData, start, count);
2876
2877     if (srcData == NULL || cnt < 0)
2878         return WINED3DERR_INVALIDCALL;
2879
2880     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
2881     for (i = 0; i < cnt; i++)
2882         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
2883
2884     for (i = start; i < cnt + start; ++i) {
2885         This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
2886         This->updateStateBlock->set.vertexShaderConstantsB[i]     = TRUE;
2887     }
2888
2889     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
2890
2891     return WINED3D_OK;
2892 }
2893
2894 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
2895     IWineD3DDevice *iface,
2896     UINT start,
2897     BOOL *dstData,
2898     UINT count) {
2899
2900     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2901     int cnt = min(count, MAX_CONST_B - start);
2902
2903     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2904             iface, dstData, start, count);
2905
2906     if (dstData == NULL || cnt < 0)
2907         return WINED3DERR_INVALIDCALL;
2908
2909     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
2910     return WINED3D_OK;
2911 }
2912
2913 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
2914     IWineD3DDevice *iface,
2915     UINT start,
2916     CONST int *srcData,
2917     UINT count) {
2918
2919     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2920     int i, cnt = min(count, MAX_CONST_I - start);
2921
2922     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2923             iface, srcData, start, count);
2924
2925     if (srcData == NULL || cnt < 0)
2926         return WINED3DERR_INVALIDCALL;
2927
2928     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
2929     for (i = 0; i < cnt; i++)
2930         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
2931            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
2932
2933     for (i = start; i < cnt + start; ++i) {
2934         This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
2935         This->updateStateBlock->set.vertexShaderConstantsI[i]     = TRUE;
2936     }
2937
2938     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
2939
2940     return WINED3D_OK;
2941 }
2942
2943 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
2944     IWineD3DDevice *iface,
2945     UINT start,
2946     int *dstData,
2947     UINT count) {
2948
2949     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2950     int cnt = min(count, MAX_CONST_I - start);
2951
2952     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2953             iface, dstData, start, count);
2954
2955     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
2956         return WINED3DERR_INVALIDCALL;
2957
2958     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
2959     return WINED3D_OK;
2960 }
2961
2962 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
2963     IWineD3DDevice *iface,
2964     UINT start,
2965     CONST float *srcData,
2966     UINT count) {
2967
2968     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2969     int i;
2970
2971     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2972             iface, srcData, start, count);
2973
2974     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
2975     if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
2976         return WINED3DERR_INVALIDCALL;
2977
2978     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
2979     if(TRACE_ON(d3d)) {
2980         for (i = 0; i < count; i++)
2981             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
2982                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
2983     }
2984
2985     for (i = start; i < count + start; ++i) {
2986         if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
2987             constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_vconstantsF), constants_entry, entry);
2988             if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
2989                 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
2990                 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
2991             }
2992             ptr->idx[ptr->count++] = i;
2993             This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
2994         }
2995         This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
2996     }
2997
2998     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
2999
3000     return WINED3D_OK;
3001 }
3002
3003 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3004     IWineD3DDevice *iface,
3005     UINT start,
3006     float *dstData,
3007     UINT count) {
3008
3009     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3010     int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3011
3012     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3013             iface, dstData, start, count);
3014
3015     if (dstData == NULL || cnt < 0)
3016         return WINED3DERR_INVALIDCALL;
3017
3018     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3019     return WINED3D_OK;
3020 }
3021
3022 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3023     DWORD i;
3024     for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
3025         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3026     }
3027 }
3028
3029 static void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3030     DWORD i, tex;
3031     /* This code can assume that GL_NV_register_combiners are supported, otherwise
3032      * it is never called.
3033      *
3034      * Rules are:
3035      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3036      * that would be really messy and require shader recompilation
3037      * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3038      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3039      * -> Whith a 1:1 mapping oneToOneTexUnitMap is set to avoid checking MAX_SAMPLERS array
3040      * entries to make pixel shaders cheaper. MAX_SAMPLERS will be 128 in dx10
3041      */
3042     if(This->stateBlock->pixelShader || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) {
3043         if(This->oneToOneTexUnitMap) {
3044             TRACE("Not touching 1:1 map\n");
3045             return;
3046         }
3047         TRACE("Restoring 1:1 texture unit mapping\n");
3048         /* Restore a 1:1 mapping */
3049         for(i = 0; i < MAX_SAMPLERS; i++) {
3050             if(This->texUnitMap[i] != i) {
3051                 This->texUnitMap[i] = i;
3052                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3053                 markTextureStagesDirty(This, i);
3054             }
3055         }
3056         This->oneToOneTexUnitMap = TRUE;
3057         return;
3058     } else {
3059         /* No pixel shader, and we do not have enough texture units available. Try to skip NULL textures
3060          * First, see if we can succeed at all
3061          */
3062         tex = 0;
3063         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3064             if(This->stateBlock->textures[i] == NULL) tex++;
3065         }
3066
3067         if(GL_LIMITS(textures) + tex < This->stateBlock->lowest_disabled_stage) {
3068             FIXME("Too many bound textures to support the combiner settings\n");
3069             return;
3070         }
3071
3072         /* Now work out the mapping */
3073         tex = 0;
3074         This->oneToOneTexUnitMap = FALSE;
3075         WARN("Non 1:1 mapping UNTESTED!\n");
3076         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3077             /* Skip NULL textures */
3078             if (!This->stateBlock->textures[i]) {
3079                 /* Map to -1, so the check below doesn't fail if a non-NULL
3080                  * texture is set on this stage */
3081                 TRACE("Mapping texture stage %d to -1\n", i);
3082                 This->texUnitMap[i] = -1;
3083
3084                 continue;
3085             }
3086
3087             TRACE("Mapping texture stage %d to unit %d\n", i, tex);
3088             if(This->texUnitMap[i] != tex) {
3089                 This->texUnitMap[i] = tex;
3090                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3091                 markTextureStagesDirty(This, i);
3092             }
3093
3094             ++tex;
3095         }
3096     }
3097 }
3098
3099 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3100     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3101     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3102     This->updateStateBlock->pixelShader         = pShader;
3103     This->updateStateBlock->changed.pixelShader = TRUE;
3104     This->updateStateBlock->set.pixelShader     = TRUE;
3105
3106     /* Handle recording of state blocks */
3107     if (This->isRecordingState) {
3108         TRACE("Recording... not performing anything\n");
3109     }
3110
3111     if (This->isRecordingState) {
3112         TRACE("Recording... not performing anything\n");
3113         return WINED3D_OK;
3114     }
3115
3116     if(pShader == oldShader) {
3117         TRACE("App is setting the old pixel shader over, nothing to do\n");
3118         return WINED3D_OK;
3119     }
3120
3121     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3122     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3123
3124     /* Rebuild the texture unit mapping if nvrc's are supported */
3125     if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3126         IWineD3DDeviceImpl_FindTexUnitMap(This);
3127     }
3128
3129     return WINED3D_OK;
3130 }
3131
3132 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3133     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3134
3135     if (NULL == ppShader) {
3136         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3137         return WINED3DERR_INVALIDCALL;
3138     }
3139
3140     *ppShader =  This->stateBlock->pixelShader;
3141     if (NULL != *ppShader) {
3142         IWineD3DPixelShader_AddRef(*ppShader);
3143     }
3144     TRACE("(%p) : returning %p\n", This, *ppShader);
3145     return WINED3D_OK;
3146 }
3147
3148 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3149     IWineD3DDevice *iface,
3150     UINT start,
3151     CONST BOOL *srcData,
3152     UINT count) {
3153
3154     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3155     int i, cnt = min(count, MAX_CONST_B - start);
3156
3157     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3158             iface, srcData, start, count);
3159
3160     if (srcData == NULL || cnt < 0)
3161         return WINED3DERR_INVALIDCALL;
3162
3163     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3164     for (i = 0; i < cnt; i++)
3165         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3166
3167     for (i = start; i < cnt + start; ++i) {
3168         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3169         This->updateStateBlock->set.pixelShaderConstantsB[i]     = TRUE;
3170     }
3171
3172     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3173
3174     return WINED3D_OK;
3175 }
3176
3177 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3178     IWineD3DDevice *iface,
3179     UINT start,
3180     BOOL *dstData,
3181     UINT count) {
3182
3183     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3184     int cnt = min(count, MAX_CONST_B - start);
3185
3186     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3187             iface, dstData, start, count);
3188
3189     if (dstData == NULL || cnt < 0)
3190         return WINED3DERR_INVALIDCALL;
3191
3192     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3193     return WINED3D_OK;
3194 }
3195
3196 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3197     IWineD3DDevice *iface,
3198     UINT start,
3199     CONST int *srcData,
3200     UINT count) {
3201
3202     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3203     int i, cnt = min(count, MAX_CONST_I - start);
3204
3205     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3206             iface, srcData, start, count);
3207
3208     if (srcData == NULL || cnt < 0)
3209         return WINED3DERR_INVALIDCALL;
3210
3211     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3212     for (i = 0; i < cnt; i++)
3213         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3214            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3215
3216     for (i = start; i < cnt + start; ++i) {
3217         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3218         This->updateStateBlock->set.pixelShaderConstantsI[i]     = TRUE;
3219     }
3220
3221     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3222
3223     return WINED3D_OK;
3224 }
3225
3226 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3227     IWineD3DDevice *iface,
3228     UINT start,
3229     int *dstData,
3230     UINT count) {
3231
3232     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3233     int cnt = min(count, MAX_CONST_I - start);
3234
3235     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3236             iface, dstData, start, count);
3237
3238     if (dstData == NULL || cnt < 0)
3239         return WINED3DERR_INVALIDCALL;
3240
3241     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3242     return WINED3D_OK;
3243 }
3244
3245 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3246     IWineD3DDevice *iface,
3247     UINT start,
3248     CONST float *srcData,
3249     UINT count) {
3250
3251     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3252     int i;
3253
3254     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3255             iface, srcData, start, count);
3256
3257     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3258     if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
3259         return WINED3DERR_INVALIDCALL;
3260
3261     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3262     if(TRACE_ON(d3d)) {
3263         for (i = 0; i < count; i++)
3264             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3265                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3266     }
3267
3268     for (i = start; i < count + start; ++i) {
3269         if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3270             constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_pconstantsF), constants_entry, entry);
3271             if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
3272                 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
3273                 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3274             }
3275             ptr->idx[ptr->count++] = i;
3276             This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3277         }
3278         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3279     }
3280
3281     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3282
3283     return WINED3D_OK;
3284 }
3285
3286 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3287     IWineD3DDevice *iface,
3288     UINT start,
3289     float *dstData,
3290     UINT count) {
3291
3292     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3293     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3294
3295     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3296             iface, dstData, start, count);
3297
3298     if (dstData == NULL || cnt < 0)
3299         return WINED3DERR_INVALIDCALL;
3300
3301     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3302     return WINED3D_OK;
3303 }
3304
3305 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3306 static HRESULT
3307 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3308     char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
3309     unsigned int i;
3310     DWORD DestFVF = dest->fvf;
3311     WINED3DVIEWPORT vp;
3312     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3313     BOOL doClip;
3314     int numTextures;
3315
3316     if (SrcFVF & WINED3DFVF_NORMAL) {
3317         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3318     }
3319
3320     if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
3321         ERR("Source has no position mask\n");
3322         return WINED3DERR_INVALIDCALL;
3323     }
3324
3325     /* We might access VBOs from this code, so hold the lock */
3326     ENTER_GL();
3327
3328     if (dest->resource.allocatedMemory == NULL) {
3329         /* This may happen if we do direct locking into a vbo. Unlikely,
3330          * but theoretically possible(ddraw processvertices test)
3331          */
3332         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3333         if(!dest->resource.allocatedMemory) {
3334             LEAVE_GL();
3335             ERR("Out of memory\n");
3336             return E_OUTOFMEMORY;
3337         }
3338         if(dest->vbo) {
3339             void *src;
3340             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3341             checkGLcall("glBindBufferARB");
3342             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3343             if(src) {
3344                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3345             }
3346             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3347             checkGLcall("glUnmapBufferARB");
3348         }
3349     }
3350
3351     /* Get a pointer into the destination vbo(create one if none exists) and
3352      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3353      */
3354     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3355         CreateVBO(dest);
3356     }
3357
3358     if(dest->vbo) {
3359         dest_conv_addr = HeapAlloc(GetProcessHeap(), 0, dwCount * get_flexible_vertex_size(DestFVF));
3360         if(!dest_conv_addr) {
3361             ERR("Out of memory\n");
3362             /* Continue without storing converted vertices */
3363         }
3364         dest_conv = dest_conv_addr;
3365     }
3366
3367     /* Should I clip?
3368      * a) WINED3DRS_CLIPPING is enabled
3369      * b) WINED3DVOP_CLIP is passed
3370      */
3371     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3372         static BOOL warned = FALSE;
3373         /*
3374          * The clipping code is not quite correct. Some things need
3375          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3376          * so disable clipping for now.
3377          * (The graphics in Half-Life are broken, and my processvertices
3378          *  test crashes with IDirect3DDevice3)
3379         doClip = TRUE;
3380          */
3381         doClip = FALSE;
3382         if(!warned) {
3383            warned = TRUE;
3384            FIXME("Clipping is broken and disabled for now\n");
3385         }
3386     } else doClip = FALSE;
3387     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3388
3389     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3390                                  WINED3DTS_VIEW,
3391                                  &view_mat);
3392     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3393                                  WINED3DTS_PROJECTION,
3394                                  &proj_mat);
3395     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3396                                  WINED3DTS_WORLDMATRIX(0),
3397                                  &world_mat);
3398
3399     TRACE("View mat:\n");
3400     TRACE("%f %f %f %f\n", view_mat.u.s._11, view_mat.u.s._12, view_mat.u.s._13, view_mat.u.s._14);
3401     TRACE("%f %f %f %f\n", view_mat.u.s._21, view_mat.u.s._22, view_mat.u.s._23, view_mat.u.s._24);
3402     TRACE("%f %f %f %f\n", view_mat.u.s._31, view_mat.u.s._32, view_mat.u.s._33, view_mat.u.s._34);
3403     TRACE("%f %f %f %f\n", view_mat.u.s._41, view_mat.u.s._42, view_mat.u.s._43, view_mat.u.s._44);
3404
3405     TRACE("Proj mat:\n");
3406     TRACE("%f %f %f %f\n", proj_mat.u.s._11, proj_mat.u.s._12, proj_mat.u.s._13, proj_mat.u.s._14);
3407     TRACE("%f %f %f %f\n", proj_mat.u.s._21, proj_mat.u.s._22, proj_mat.u.s._23, proj_mat.u.s._24);
3408     TRACE("%f %f %f %f\n", proj_mat.u.s._31, proj_mat.u.s._32, proj_mat.u.s._33, proj_mat.u.s._34);
3409     TRACE("%f %f %f %f\n", proj_mat.u.s._41, proj_mat.u.s._42, proj_mat.u.s._43, proj_mat.u.s._44);
3410
3411     TRACE("World mat:\n");
3412     TRACE("%f %f %f %f\n", world_mat.u.s._11, world_mat.u.s._12, world_mat.u.s._13, world_mat.u.s._14);
3413     TRACE("%f %f %f %f\n", world_mat.u.s._21, world_mat.u.s._22, world_mat.u.s._23, world_mat.u.s._24);
3414     TRACE("%f %f %f %f\n", world_mat.u.s._31, world_mat.u.s._32, world_mat.u.s._33, world_mat.u.s._34);
3415     TRACE("%f %f %f %f\n", world_mat.u.s._41, world_mat.u.s._42, world_mat.u.s._43, world_mat.u.s._44);
3416
3417     /* Get the viewport */
3418     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3419     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3420           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3421
3422     multiply_matrix(&mat,&view_mat,&world_mat);
3423     multiply_matrix(&mat,&proj_mat,&mat);
3424
3425     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3426
3427     for (i = 0; i < dwCount; i+= 1) {
3428         unsigned int tex_index;
3429
3430         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3431              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3432             /* The position first */
3433             float *p =
3434               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
3435             float x, y, z, rhw;
3436             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3437
3438             /* Multiplication with world, view and projection matrix */
3439             x =   (p[0] * mat.u.s._11) + (p[1] * mat.u.s._21) + (p[2] * mat.u.s._31) + (1.0 * mat.u.s._41);
3440             y =   (p[0] * mat.u.s._12) + (p[1] * mat.u.s._22) + (p[2] * mat.u.s._32) + (1.0 * mat.u.s._42);
3441             z =   (p[0] * mat.u.s._13) + (p[1] * mat.u.s._23) + (p[2] * mat.u.s._33) + (1.0 * mat.u.s._43);
3442             rhw = (p[0] * mat.u.s._14) + (p[1] * mat.u.s._24) + (p[2] * mat.u.s._34) + (1.0 * mat.u.s._44);
3443
3444             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3445
3446             /* WARNING: The following things are taken from d3d7 and were not yet checked
3447              * against d3d8 or d3d9!
3448              */
3449
3450             /* Clipping conditions: From
3451              * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
3452              *
3453              * A vertex is clipped if it does not match the following requirements
3454              * -rhw < x <= rhw
3455              * -rhw < y <= rhw
3456              *    0 < z <= rhw
3457              *    0 < rhw ( Not in d3d7, but tested in d3d7)
3458              *
3459              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3460              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3461              *
3462              */
3463
3464             if( !doClip ||
3465                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3466                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
3467                   ( rhw > eps ) ) ) {
3468
3469                 /* "Normal" viewport transformation (not clipped)
3470                  * 1) The values are divided by rhw
3471                  * 2) The y axis is negative, so multiply it with -1
3472                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3473                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3474                  * 4) Multiply x with Width/2 and add Width/2
3475                  * 5) The same for the height
3476                  * 6) Add the viewpoint X and Y to the 2D coordinates and
3477                  *    The minimum Z value to z
3478                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3479                  *
3480                  * Well, basically it's simply a linear transformation into viewport
3481                  * coordinates
3482                  */
3483
3484                 x /= rhw;
3485                 y /= rhw;
3486                 z /= rhw;
3487
3488                 y *= -1;
3489
3490                 x *= vp.Width / 2;
3491                 y *= vp.Height / 2;
3492                 z *= vp.MaxZ - vp.MinZ;
3493
3494                 x += vp.Width / 2 + vp.X;
3495                 y += vp.Height / 2 + vp.Y;
3496                 z += vp.MinZ;
3497
3498                 rhw = 1 / rhw;
3499             } else {
3500                 /* That vertex got clipped
3501                  * Contrary to OpenGL it is not dropped completely, it just
3502                  * undergoes a different calculation.
3503                  */
3504                 TRACE("Vertex got clipped\n");
3505                 x += rhw;
3506                 y += rhw;
3507
3508                 x  /= 2;
3509                 y  /= 2;
3510
3511                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3512                  * outside of the main vertex buffer memory. That needs some more
3513                  * investigation...
3514                  */
3515             }
3516
3517             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3518
3519
3520             ( (float *) dest_ptr)[0] = x;
3521             ( (float *) dest_ptr)[1] = y;
3522             ( (float *) dest_ptr)[2] = z;
3523             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3524
3525             dest_ptr += 3 * sizeof(float);
3526
3527             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3528                 dest_ptr += sizeof(float);
3529             }
3530
3531             if(dest_conv) {
3532                 float w = 1 / rhw;
3533                 ( (float *) dest_conv)[0] = x * w;
3534                 ( (float *) dest_conv)[1] = y * w;
3535                 ( (float *) dest_conv)[2] = z * w;
3536                 ( (float *) dest_conv)[3] = w;
3537
3538                 dest_conv += 3 * sizeof(float);
3539
3540                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3541                     dest_conv += sizeof(float);
3542                 }
3543             }
3544         }
3545         if (DestFVF & WINED3DFVF_PSIZE) {
3546             dest_ptr += sizeof(DWORD);
3547             if(dest_conv) dest_conv += sizeof(DWORD);
3548         }
3549         if (DestFVF & WINED3DFVF_NORMAL) {
3550             float *normal =
3551               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
3552             /* AFAIK this should go into the lighting information */
3553             FIXME("Didn't expect the destination to have a normal\n");
3554             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3555             if(dest_conv) {
3556                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
3557             }
3558         }
3559
3560         if (DestFVF & WINED3DFVF_DIFFUSE) {
3561             DWORD *color_d = 
3562               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
3563             if(!color_d) {
3564                 static BOOL warned = FALSE;
3565
3566                 if(!warned) {
3567                     ERR("No diffuse color in source, but destination has one\n");
3568                     warned = TRUE;
3569                 }
3570
3571                 *( (DWORD *) dest_ptr) = 0xffffffff;
3572                 dest_ptr += sizeof(DWORD);
3573
3574                 if(dest_conv) {
3575                     *( (DWORD *) dest_conv) = 0xffffffff;
3576                     dest_conv += sizeof(DWORD);
3577                 }
3578             }
3579             else {
3580                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3581                 if(dest_conv) {
3582                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
3583                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
3584                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
3585                     dest_conv += sizeof(DWORD);
3586                 }
3587             }
3588         }
3589
3590         if (DestFVF & WINED3DFVF_SPECULAR) { 
3591             /* What's the color value in the feedback buffer? */
3592             DWORD *color_s = 
3593               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
3594             if(!color_s) {
3595                 static BOOL warned = FALSE;
3596
3597                 if(!warned) {
3598                     ERR("No specular color in source, but destination has one\n");
3599                     warned = TRUE;
3600                 }
3601
3602                 *( (DWORD *) dest_ptr) = 0xFF000000;
3603                 dest_ptr += sizeof(DWORD);
3604
3605                 if(dest_conv) {
3606                     *( (DWORD *) dest_conv) = 0xFF000000;
3607                     dest_conv += sizeof(DWORD);
3608                 }
3609             }
3610             else {
3611                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3612                 if(dest_conv) {
3613                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
3614                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
3615                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
3616                     dest_conv += sizeof(DWORD);
3617                 }
3618             }
3619         }
3620
3621         for (tex_index = 0; tex_index < numTextures; tex_index++) {
3622             float *tex_coord =
3623               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
3624                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
3625             if(!tex_coord) {
3626                 ERR("No source texture, but destination requests one\n");
3627                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3628                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3629             }
3630             else {
3631                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3632                 if(dest_conv) {
3633                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3634                 }
3635             }
3636         }
3637     }
3638
3639     if(dest_conv) {
3640         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3641         checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
3642         GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
3643                                       dwCount * get_flexible_vertex_size(DestFVF),
3644                                       dest_conv_addr));
3645         checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
3646         HeapFree(GetProcessHeap(), 0, dest_conv_addr);
3647     }
3648
3649     LEAVE_GL();
3650
3651     return WINED3D_OK;
3652 }
3653 #undef copy_and_next
3654
3655 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3656     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3657     IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
3658     WineDirect3DVertexStridedData strided;
3659     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
3660
3661     if (!SrcImpl) {
3662         WARN("NULL source vertex buffer\n");
3663         return WINED3DERR_INVALIDCALL;
3664     }
3665     /* We don't need the source vbo because this buffer is only used as
3666      * a source for ProcessVertices. Avoid wasting resources by converting the
3667      * buffer and loading the VBO
3668      */
3669     if(SrcImpl->vbo) {
3670         TRACE("Releasing the source vbo, it won't be needed\n");
3671
3672         if(!SrcImpl->resource.allocatedMemory) {
3673             /* Rescue the data from the buffer */
3674             void *src;
3675             SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
3676             if(!SrcImpl->resource.allocatedMemory) {
3677                 ERR("Out of memory\n");
3678                 return E_OUTOFMEMORY;
3679             }
3680
3681             ENTER_GL();
3682             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
3683             checkGLcall("glBindBufferARB");
3684
3685             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3686             if(src) {
3687                 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
3688             }
3689
3690             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3691             checkGLcall("glUnmapBufferARB");
3692         } else {
3693             ENTER_GL();
3694         }
3695
3696         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
3697         checkGLcall("glBindBufferARB");
3698         GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
3699         checkGLcall("glDeleteBuffersARB");
3700         LEAVE_GL();
3701
3702         SrcImpl->vbo = 0;
3703     }
3704
3705     memset(&strided, 0, sizeof(strided));
3706     primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0, 0);
3707
3708     return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
3709 }
3710
3711 /*****
3712  * Get / Set Texture Stage States
3713  * TODO: Verify against dx9 definitions
3714  *****/
3715 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3716     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3717     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
3718
3719     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3720
3721     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3722
3723     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3724     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
3725     This->updateStateBlock->textureState[Stage][Type]         = Value;
3726
3727     if (This->isRecordingState) {
3728         TRACE("Recording... not performing anything\n");
3729         return WINED3D_OK;
3730     }
3731
3732     /* Checked after the assignments to allow proper stateblock recording */
3733     if(oldValue == Value) {
3734         TRACE("App is setting the old value over, nothing to do\n");
3735         return WINED3D_OK;
3736     }
3737
3738     if(Stage > This->stateBlock->lowest_disabled_stage &&
3739        StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
3740         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
3741          * Changes in other states are important on disabled stages too
3742          */
3743         return WINED3D_OK;
3744     }
3745
3746     if(Type == WINED3DTSS_COLOROP) {
3747         int i;
3748
3749         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
3750             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
3751              * they have to be disabled
3752              *
3753              * The current stage is dirtified below.
3754              */
3755             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
3756                 TRACE("Additionally dirtifying stage %d\n", i);
3757                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3758             }
3759             This->stateBlock->lowest_disabled_stage = Stage;
3760             TRACE("New lowest disabled: %d\n", Stage);
3761         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
3762             /* Previously disabled stage enabled. Stages above it may need enabling
3763              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
3764              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
3765              *
3766              * Again stage Stage doesn't need to be dirtified here, it is handled below.
3767              */
3768
3769             for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
3770                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
3771                     break;
3772                 }
3773                 TRACE("Additionally dirtifying stage %d due to enable\n", i);
3774                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3775             }
3776             This->stateBlock->lowest_disabled_stage = i;
3777             TRACE("New lowest disabled: %d\n", i);
3778         }
3779         if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3780             /* TODO: Built a stage -> texture unit mapping for register combiners */
3781         }
3782     }
3783
3784     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
3785
3786     /* Rebuild the stage -> gl texture unit mapping if register combiners are supported
3787      * If there is a pixel shader there will be a 1:1 mapping, no need to touch it. SetPixelShader
3788      * will call FindTexUnitMap too.
3789      */
3790     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3791         IWineD3DDeviceImpl_FindTexUnitMap(This);
3792     }
3793     return WINED3D_OK;
3794 }
3795
3796 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3797     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3798     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3799     *pValue = This->updateStateBlock->textureState[Stage][Type];
3800     return WINED3D_OK;
3801 }
3802
3803 /*****
3804  * Get / Set Texture
3805  *****/
3806 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3807
3808     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3809     IWineD3DBaseTexture   *oldTexture;
3810
3811     oldTexture = This->updateStateBlock->textures[Stage];
3812     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
3813
3814 #if 0 /* TODO: check so vertex textures */
3815     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
3816         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
3817         return WINED3D_OK;
3818     }
3819 #endif
3820
3821     if(pTexture != NULL) {
3822         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
3823          */
3824         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
3825             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
3826             return WINED3DERR_INVALIDCALL;
3827         }
3828         This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
3829     }
3830
3831     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
3832     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
3833
3834     This->updateStateBlock->set.textures[Stage]     = TRUE;
3835     This->updateStateBlock->changed.textures[Stage] = TRUE;
3836     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
3837     This->updateStateBlock->textures[Stage]         = pTexture;
3838
3839     /* Handle recording of state blocks */
3840     if (This->isRecordingState) {
3841         TRACE("Recording... not performing anything\n");
3842         return WINED3D_OK;
3843     }
3844
3845     if(oldTexture == pTexture) {
3846         TRACE("App is setting the same texture again, nothing to do\n");
3847         return WINED3D_OK;
3848     }
3849
3850     /** NOTE: MSDN says that setTexture increases the reference count,
3851     * and the the application nust set the texture back to null (or have a leaky application),
3852     * This means we should pass the refcount up to the parent
3853      *******************************/
3854     if (NULL != This->updateStateBlock->textures[Stage]) {
3855         IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
3856         ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
3857
3858         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
3859         if(oldTexture == NULL && Stage < MAX_TEXTURES) {
3860             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
3861              * so the COLOROP and ALPHAOP have to be dirtified.
3862              */
3863             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
3864             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
3865         }
3866         if(bindCount == 1) {
3867             new->baseTexture.sampler = Stage;
3868         }
3869         /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
3870
3871     }
3872
3873     if (NULL != oldTexture) {
3874         IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
3875         LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
3876
3877         IWineD3DBaseTexture_Release(oldTexture);
3878         if(pTexture == NULL && Stage < MAX_TEXTURES) {
3879             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
3880             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
3881         }
3882
3883         if(bindCount && old->baseTexture.sampler == Stage) {
3884             int i;
3885             /* Have to do a search for the other sampler(s) where the texture is bound to
3886              * Shouldn't happen as long as apps bind a texture only to one stage
3887              */
3888             TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
3889             for(i = 0; i < GL_LIMITS(sampler_stages); i++) {
3890                 if(This->updateStateBlock->textures[i] == oldTexture) {
3891                     old->baseTexture.sampler = i;
3892                     break;
3893                 }
3894             }
3895         }
3896     }
3897
3898     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
3899
3900     /* Verify the texture unit mapping(and rebuild it if needed) if we use nvrcs and no
3901      * pixel shader is used
3902      */
3903     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3904         IWineD3DDeviceImpl_FindTexUnitMap(This);
3905     }
3906
3907     return WINED3D_OK;
3908 }
3909
3910 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3911     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3912     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
3913
3914     *ppTexture=This->stateBlock->textures[Stage];
3915     if (*ppTexture)
3916         IWineD3DBaseTexture_AddRef(*ppTexture);
3917
3918     return WINED3D_OK;
3919 }
3920
3921 /*****
3922  * Get Back Buffer
3923  *****/
3924 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
3925                                                 IWineD3DSurface **ppBackBuffer) {
3926     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3927     IWineD3DSwapChain *swapChain;
3928     HRESULT hr;
3929
3930     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3931
3932     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
3933     if (hr == WINED3D_OK) {
3934         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
3935             IWineD3DSwapChain_Release(swapChain);
3936     } else {
3937         *ppBackBuffer = NULL;
3938     }
3939     return hr;
3940 }
3941
3942 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
3943     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3944     WARN("(%p) : stub, calling idirect3d for now\n", This);
3945     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
3946 }
3947
3948 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
3949     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3950     IWineD3DSwapChain *swapChain;
3951     HRESULT hr;
3952
3953     if(iSwapChain > 0) {
3954         hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
3955         if (hr == WINED3D_OK) {
3956             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
3957             IWineD3DSwapChain_Release(swapChain);
3958         } else {
3959             FIXME("(%p) Error getting display mode\n", This);
3960         }
3961     } else {
3962         /* Don't read the real display mode,
3963            but return the stored mode instead. X11 can't change the color
3964            depth, and some apps are pretty angry if they SetDisplayMode from
3965            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
3966
3967            Also don't relay to the swapchain because with ddraw it's possible
3968            that there isn't a swapchain at all */
3969         pMode->Width = This->ddraw_width;
3970         pMode->Height = This->ddraw_height;
3971         pMode->Format = This->ddraw_format;
3972         pMode->RefreshRate = 0;
3973         hr = WINED3D_OK;
3974     }
3975
3976     return hr;
3977 }
3978
3979 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
3980     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3981     TRACE("(%p)->(%p)\n", This, hWnd);
3982
3983     if(This->ddraw_fullscreen) {
3984         if(This->ddraw_window && This->ddraw_window != hWnd) {
3985             IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
3986         }
3987         if(hWnd && This->ddraw_window != hWnd) {
3988             IWineD3DDeviceImpl_SetupFullscreenWindow(iface, hWnd);
3989         }
3990     }
3991
3992     This->ddraw_window = hWnd;
3993     return WINED3D_OK;
3994 }
3995
3996 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
3997     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3998     TRACE("(%p)->(%p)\n", This, hWnd);
3999
4000     *hWnd = This->ddraw_window;
4001     return WINED3D_OK;
4002 }
4003
4004 /*****
4005  * Stateblock related functions
4006  *****/
4007
4008 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4009     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4010     IWineD3DStateBlockImpl *object;
4011     HRESULT temp_result;
4012     int i;
4013
4014     TRACE("(%p)\n", This);
4015     
4016     if (This->isRecordingState) {
4017         return WINED3DERR_INVALIDCALL;
4018     }
4019     
4020     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4021     if (NULL == object ) {
4022         FIXME("(%p)Error allocating memory for stateblock\n", This);
4023         return E_OUTOFMEMORY;
4024     }
4025     TRACE("(%p) created object %p\n", This, object);
4026     object->wineD3DDevice= This;
4027     /** FIXME: object->parent       = parent; **/
4028     object->parent       = NULL;
4029     object->blockType    = WINED3DSBT_ALL;
4030     object->ref          = 1;
4031     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4032
4033     for(i = 0; i < LIGHTMAP_SIZE; i++) {
4034         list_init(&object->lightMap[i]);
4035     }
4036
4037     temp_result = allocate_shader_constants(object);
4038     if (WINED3D_OK != temp_result)
4039         return temp_result;
4040
4041     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4042     This->updateStateBlock = object;
4043     This->isRecordingState = TRUE;
4044
4045     TRACE("(%p) recording stateblock %p\n",This , object);
4046     return WINED3D_OK;
4047 }
4048
4049 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4050     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4051
4052     if (!This->isRecordingState) {
4053         FIXME("(%p) not recording! returning error\n", This);
4054         *ppStateBlock = NULL;
4055         return WINED3DERR_INVALIDCALL;
4056     }
4057
4058     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4059     This->isRecordingState = FALSE;
4060     This->updateStateBlock = This->stateBlock;
4061     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4062     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4063     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4064     return WINED3D_OK;
4065 }
4066
4067 /*****
4068  * Scene related functions
4069  *****/
4070 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4071     /* At the moment we have no need for any functionality at the beginning
4072        of a scene                                                          */
4073     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4074     TRACE("(%p)\n", This);
4075
4076     if(This->inScene) {
4077         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4078         return WINED3DERR_INVALIDCALL;
4079     }
4080     This->inScene = TRUE;
4081     return WINED3D_OK;
4082 }
4083
4084 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4085     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4086     TRACE("(%p)\n", This);
4087
4088     if(!This->inScene) {
4089         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4090         return WINED3DERR_INVALIDCALL;
4091     }
4092
4093     ENTER_GL();
4094     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4095     glFlush();
4096     checkGLcall("glFlush");
4097     LEAVE_GL();
4098
4099     This->inScene = FALSE;
4100     return WINED3D_OK;
4101 }
4102
4103 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4104                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4105                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4106     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4107     IWineD3DSwapChain *swapChain = NULL;
4108     int i;
4109     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4110
4111     TRACE("(%p) Presenting the frame\n", This);
4112
4113     for(i = 0 ; i < swapchains ; i ++) {
4114
4115         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4116         TRACE("presentinng chain %d, %p\n", i, swapChain);
4117         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4118         IWineD3DSwapChain_Release(swapChain);
4119     }
4120
4121     return WINED3D_OK;
4122 }
4123
4124 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4125                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4126     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4127
4128     GLbitfield     glMask = 0;
4129     unsigned int   i;
4130     CONST WINED3DRECT* curRect;
4131
4132     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
4133           Count, pRects, Flags, Z, Stencil);
4134
4135     if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) {
4136         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4137         /* TODO: What about depth stencil buffers without stencil bits? */
4138         return WINED3DERR_INVALIDCALL;
4139     }
4140
4141     ENTER_GL();
4142
4143     glEnable(GL_SCISSOR_TEST);
4144     checkGLcall("glEnable GL_SCISSOR_TEST");
4145     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
4146     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
4147
4148     if (Count > 0 && pRects) {
4149         curRect = pRects;
4150     } else {
4151         curRect = NULL;
4152     }
4153
4154     /* Only set the values up once, as they are not changing */
4155     if (Flags & WINED3DCLEAR_STENCIL) {
4156         glClearStencil(Stencil);
4157         checkGLcall("glClearStencil");
4158         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4159         glStencilMask(0xFFFFFFFF);
4160     }
4161
4162     if (Flags & WINED3DCLEAR_ZBUFFER) {
4163         glDepthMask(GL_TRUE);
4164         glClearDepth(Z);
4165         checkGLcall("glClearDepth");
4166         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4167         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4168     }
4169
4170     if (Flags & WINED3DCLEAR_TARGET) {
4171         TRACE("Clearing screen with glClear to color %x\n", Color);
4172         glClearColor(D3DCOLOR_R(Color),
4173                      D3DCOLOR_G(Color),
4174                      D3DCOLOR_B(Color),
4175                      D3DCOLOR_A(Color));
4176         checkGLcall("glClearColor");
4177
4178         /* Clear ALL colors! */
4179         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4180         glMask = glMask | GL_COLOR_BUFFER_BIT;
4181     }
4182
4183     if (!curRect) {
4184         glScissor(This->stateBlock->viewport.X,
4185                   (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
4186                   (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4187                    This->stateBlock->viewport.Width,
4188                    This->stateBlock->viewport.Height);
4189         checkGLcall("glScissor");
4190         glClear(glMask);
4191         checkGLcall("glClear");
4192     } else {
4193         /* Now process each rect in turn */
4194         for (i = 0; i < Count; i++) {
4195             /* Note gl uses lower left, width/height */
4196             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4197                   curRect[i].x1, curRect[i].y1, curRect[i].x2, curRect[i].y2,
4198                   curRect[i].x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect[i].y2),
4199                   curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4200
4201             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
4202              * The rectangle is not cleared, no error is returned, but further rectanlges are
4203              * still cleared if they are valid
4204              */
4205             if(curRect[i].x1 > curRect[i].x2 || curRect[i].y1 > curRect[i].y2) {
4206                 TRACE("Rectangle with negative dimensions, ignoring\n");
4207                 continue;
4208             }
4209
4210             glScissor(curRect[i].x1, ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect[i].y2,
4211                         curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4212             checkGLcall("glScissor");
4213
4214             glClear(glMask);
4215             checkGLcall("glClear");
4216         }
4217     }
4218
4219     /* Restore the old values (why..?) */
4220     if (Flags & WINED3DCLEAR_STENCIL) {
4221         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4222     }
4223     if (Flags & WINED3DCLEAR_TARGET) {
4224         DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
4225         glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4226                     mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4227                     mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4228                     mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4229     }
4230
4231     LEAVE_GL();
4232
4233     /* Dirtify the target surface for now. If the surface is locked regularily, and an up to date sysmem copy exists,
4234      * it is most likely more efficient to perform a clear on the sysmem copy too isntead of downloading it
4235      */
4236     ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags |= SFLAG_GLDIRTY;
4237     return WINED3D_OK;
4238 }
4239
4240 /*****
4241  * Drawing functions
4242  *****/
4243 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4244                                                 UINT PrimitiveCount) {
4245
4246     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4247     This->stateBlock->streamIsUP = FALSE;
4248
4249     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4250                                debug_d3dprimitivetype(PrimitiveType),
4251                                StartVertex, PrimitiveCount);
4252
4253     if(This->stateBlock->loadBaseVertexIndex != 0) {
4254         This->stateBlock->loadBaseVertexIndex = 0;
4255         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4256     }
4257     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4258     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4259                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4260     return WINED3D_OK;
4261 }
4262
4263 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4264 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4265                                                            WINED3DPRIMITIVETYPE PrimitiveType,
4266                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4267
4268     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4269     UINT                 idxStride = 2;
4270     IWineD3DIndexBuffer *pIB;
4271     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
4272     GLuint vbo;
4273
4274     pIB = This->stateBlock->pIndexData;
4275     This->stateBlock->streamIsUP = FALSE;
4276     vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
4277
4278     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
4279           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4280           minIndex, NumVertices, startIndex, primCount);
4281
4282     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4283     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4284         idxStride = 2;
4285     } else {
4286         idxStride = 4;
4287     }
4288
4289     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4290         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4291         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4292     }
4293
4294     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
4295                    idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4296
4297     return WINED3D_OK;
4298 }
4299
4300 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4301                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4302                                                     UINT VertexStreamZeroStride) {
4303     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4304
4305     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4306              debug_d3dprimitivetype(PrimitiveType),
4307              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4308
4309     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4310     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4311     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4312     This->stateBlock->streamIsUP = TRUE;
4313     This->stateBlock->loadBaseVertexIndex = 0;
4314
4315     /* TODO: Only mark dirty if drawing from a different UP address */
4316     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4317
4318     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4319                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4320
4321     /* MSDN specifies stream zero settings must be set to NULL */
4322     This->stateBlock->streamStride[0] = 0;
4323     This->stateBlock->streamSource[0] = NULL;
4324
4325     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4326      * the new stream sources or use UP drawing again
4327      */
4328     return WINED3D_OK;
4329 }
4330
4331 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4332                                                              UINT MinVertexIndex, UINT NumVertices,
4333                                                              UINT PrimitiveCount, CONST void* pIndexData,
4334                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4335                                                              UINT VertexStreamZeroStride) {
4336     int                 idxStride;
4337     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4338
4339     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4340              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4341              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4342              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4343
4344     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4345         idxStride = 2;
4346     } else {
4347         idxStride = 4;
4348     }
4349
4350     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4351     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4352     This->stateBlock->streamIsUP = TRUE;
4353     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4354
4355     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4356     This->stateBlock->baseVertexIndex = 0;
4357     This->stateBlock->loadBaseVertexIndex = 0;
4358     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4359     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4360     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4361
4362     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4363
4364     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4365     This->stateBlock->streamSource[0] = NULL;
4366     This->stateBlock->streamStride[0] = 0;
4367     This->stateBlock->pIndexData = NULL;
4368     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4369      * SetStreamSource to specify a vertex buffer
4370      */
4371
4372     return WINED3D_OK;
4373 }
4374
4375 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4376     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4377
4378     /* Mark the state dirty until we have nicer tracking
4379      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4380      * that value.
4381      */
4382     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4383     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4384     This->stateBlock->baseVertexIndex = 0;
4385     This->up_strided = DrawPrimStrideData;
4386     This->stateBlock->streamIsUP = TRUE;
4387     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
4388     This->up_strided = NULL;
4389     return WINED3D_OK;
4390 }
4391  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4392 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4393     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4394     HRESULT hr = WINED3D_OK;
4395     WINED3DRESOURCETYPE sourceType;
4396     WINED3DRESOURCETYPE destinationType;
4397     int i ,levels;
4398
4399     /* TODO: think about moving the code into IWineD3DBaseTexture  */
4400
4401     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4402
4403     /* verify that the source and destination textures aren't NULL */
4404     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4405         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4406              This, pSourceTexture, pDestinationTexture);
4407         hr = WINED3DERR_INVALIDCALL;
4408     }
4409
4410     if (pSourceTexture == pDestinationTexture) {
4411         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4412              This, pSourceTexture, pDestinationTexture);
4413         hr = WINED3DERR_INVALIDCALL;
4414     }
4415     /* Verify that the source and destination textures are the same type */
4416     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
4417     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4418
4419     if (sourceType != destinationType) {
4420         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
4421              This);
4422         hr = WINED3DERR_INVALIDCALL;
4423     }
4424
4425     /* check that both textures have the identical numbers of levels  */
4426     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4427         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4428         hr = WINED3DERR_INVALIDCALL;
4429     }
4430
4431     if (WINED3D_OK == hr) {
4432
4433         /* Make sure that the destination texture is loaded */
4434         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4435
4436         /* Update every surface level of the texture */
4437         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4438
4439         switch (sourceType) {
4440         case WINED3DRTYPE_TEXTURE:
4441             {
4442                 IWineD3DSurface *srcSurface;
4443                 IWineD3DSurface *destSurface;
4444
4445                 for (i = 0 ; i < levels ; ++i) {
4446                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
4447                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4448                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4449                     IWineD3DSurface_Release(srcSurface);
4450                     IWineD3DSurface_Release(destSurface);
4451                     if (WINED3D_OK != hr) {
4452                         WARN("(%p) : Call to update surface failed\n", This);
4453                         return hr;
4454                     }
4455                 }
4456             }
4457             break;
4458         case WINED3DRTYPE_CUBETEXTURE:
4459             {
4460                 IWineD3DSurface *srcSurface;
4461                 IWineD3DSurface *destSurface;
4462                 WINED3DCUBEMAP_FACES faceType;
4463
4464                 for (i = 0 ; i < levels ; ++i) {
4465                     /* Update each cube face */
4466                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4467                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
4468                         if (WINED3D_OK != hr) {
4469                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4470                         } else {
4471                             TRACE("Got srcSurface %p\n", srcSurface);
4472                         }
4473                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4474                         if (WINED3D_OK != hr) {
4475                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4476                         } else {
4477                             TRACE("Got desrSurface %p\n", destSurface);
4478                         }
4479                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4480                         IWineD3DSurface_Release(srcSurface);
4481                         IWineD3DSurface_Release(destSurface);
4482                         if (WINED3D_OK != hr) {
4483                             WARN("(%p) : Call to update surface failed\n", This);
4484                             return hr;
4485                         }
4486                     }
4487                 }
4488             }
4489             break;
4490 #if 0 /* TODO: Add support for volume textures */
4491         case WINED3DRTYPE_VOLUMETEXTURE:
4492             {
4493                 IWineD3DVolume  srcVolume  = NULL;
4494                 IWineD3DSurface destVolume = NULL;
4495
4496                 for (i = 0 ; i < levels ; ++i) {
4497                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
4498                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4499                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4500                     IWineD3DVolume_Release(srcSurface);
4501                     IWineD3DVolume_Release(destSurface);
4502                     if (WINED3D_OK != hr) {
4503                         WARN("(%p) : Call to update volume failed\n", This);
4504                         return hr;
4505                     }
4506                 }
4507             }
4508             break;
4509 #endif
4510         default:
4511             FIXME("(%p) : Unsupported source and destination type\n", This);
4512             hr = WINED3DERR_INVALIDCALL;
4513         }
4514     }
4515
4516     return hr;
4517 }
4518
4519 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4520     IWineD3DSwapChain *swapChain;
4521     HRESULT hr;
4522     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4523     if(hr == WINED3D_OK) {
4524         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4525                 IWineD3DSwapChain_Release(swapChain);
4526     }
4527     return hr;
4528 }
4529
4530 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4531     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4532     /* return a sensible default */
4533     *pNumPasses = 1;
4534     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
4535     FIXME("(%p) : stub\n", This);
4536     return WINED3D_OK;
4537 }
4538
4539 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4540     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4541     int j;
4542     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4543     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4544         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4545         return WINED3DERR_INVALIDCALL;
4546     }
4547     for (j = 0; j < 256; ++j) {
4548         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
4549         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4550         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
4551         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4552     }
4553     TRACE("(%p) : returning\n", This);
4554     return WINED3D_OK;
4555 }
4556
4557 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4558     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4559     int j;
4560     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4561     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4562         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4563         return WINED3DERR_INVALIDCALL;
4564     }
4565     for (j = 0; j < 256; ++j) {
4566         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
4567         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4568         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
4569         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4570     }
4571     TRACE("(%p) : returning\n", This);
4572     return WINED3D_OK;
4573 }
4574
4575 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4576     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4577     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4578     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4579         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4580         return WINED3DERR_INVALIDCALL;
4581     }
4582     /*TODO: stateblocks */
4583     This->currentPalette = PaletteNumber;
4584     TRACE("(%p) : returning\n", This);
4585     return WINED3D_OK;
4586 }
4587
4588 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4589     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4590     if (PaletteNumber == NULL) {
4591         WARN("(%p) : returning Invalid Call\n", This);
4592         return WINED3DERR_INVALIDCALL;
4593     }
4594     /*TODO: stateblocks */
4595     *PaletteNumber = This->currentPalette;
4596     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
4597     return WINED3D_OK;
4598 }
4599
4600 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4601     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4602     static BOOL showFixmes = TRUE;
4603     if (showFixmes) {
4604         FIXME("(%p) : stub\n", This);
4605         showFixmes = FALSE;
4606     }
4607
4608     This->softwareVertexProcessing = bSoftware;
4609     return WINED3D_OK;
4610 }
4611
4612
4613 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4614     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4615     static BOOL showFixmes = TRUE;
4616     if (showFixmes) {
4617         FIXME("(%p) : stub\n", This);
4618         showFixmes = FALSE;
4619     }
4620     return This->softwareVertexProcessing;
4621 }
4622
4623
4624 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
4625     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4626     IWineD3DSwapChain *swapChain;
4627     HRESULT hr;
4628
4629     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4630
4631     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4632     if(hr == WINED3D_OK){
4633         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4634         IWineD3DSwapChain_Release(swapChain);
4635     }else{
4636         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
4637     }
4638     return hr;
4639 }
4640
4641
4642 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4643     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4644     static BOOL showfixmes = TRUE;
4645     if(nSegments != 0.0f) {
4646         if( showfixmes) {
4647             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4648             showfixmes = FALSE;
4649         }
4650     }
4651     return WINED3D_OK;
4652 }
4653
4654 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4655     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656     static BOOL showfixmes = TRUE;
4657     if( showfixmes) {
4658         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4659         showfixmes = FALSE;
4660     }
4661     return 0.0f;
4662 }
4663
4664 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4665     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
4666     /** TODO: remove casts to IWineD3DSurfaceImpl
4667      *       NOTE: move code to surface to accomplish this
4668       ****************************************/
4669     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
4670     int srcWidth, srcHeight;
4671     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4672     WINED3DFORMAT destFormat, srcFormat;
4673     UINT          destSize;
4674     int srcLeft, destLeft, destTop;
4675     WINED3DPOOL       srcPool, destPool;
4676     int offset    = 0;
4677     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4678     glDescriptor *glDescription = NULL;
4679
4680     WINED3DSURFACE_DESC  winedesc;
4681
4682     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
4683     memset(&winedesc, 0, sizeof(winedesc));
4684     winedesc.Width  = &srcSurfaceWidth;
4685     winedesc.Height = &srcSurfaceHeight;
4686     winedesc.Pool   = &srcPool;
4687     winedesc.Format = &srcFormat;
4688
4689     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4690
4691     winedesc.Width  = &destSurfaceWidth;
4692     winedesc.Height = &destSurfaceHeight;
4693     winedesc.Pool   = &destPool;
4694     winedesc.Format = &destFormat;
4695     winedesc.Size   = &destSize;
4696
4697     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4698
4699     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
4700         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
4701         return WINED3DERR_INVALIDCALL;
4702     }
4703
4704     if (destFormat == WINED3DFMT_UNKNOWN) {
4705         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
4706         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
4707
4708         /* Get the update surface description */
4709         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4710     }
4711
4712     ENTER_GL();
4713     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4714         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
4715         checkGLcall("glActiveTextureARB");
4716     }
4717
4718     /* Make sure the surface is loaded and up to date */
4719     IWineD3DSurface_PreLoad(pDestinationSurface);
4720
4721     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4722
4723     /* this needs to be done in lines if the sourceRect != the sourceWidth */
4724     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
4725     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
4726     srcLeft    = pSourceRect ? pSourceRect->left : 0;
4727     destLeft   = pDestPoint  ? pDestPoint->x : 0;
4728     destTop    = pDestPoint  ? pDestPoint->y : 0;
4729
4730
4731     /* This function doesn't support compressed textures
4732     the pitch is just bytesPerPixel * width */
4733     if(srcWidth != srcSurfaceWidth  || srcLeft ){
4734         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4735         offset   += srcLeft * pSrcSurface->bytesPerPixel;
4736         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4737     }
4738     /* TODO DXT formats */
4739
4740     if(pSourceRect != NULL && pSourceRect->top != 0){
4741        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4742     }
4743     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4744     ,This
4745     ,glDescription->level
4746     ,destLeft
4747     ,destTop
4748     ,srcWidth
4749     ,srcHeight
4750     ,glDescription->glFormat
4751     ,glDescription->glType
4752     ,IWineD3DSurface_GetData(pSourceSurface)
4753     );
4754
4755     /* Sanity check */
4756     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4757
4758         /* need to lock the surface to get the data */
4759         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4760     }
4761
4762     /* TODO: Cube and volume support */
4763     if(rowoffset != 0){
4764         /* not a whole row so we have to do it a line at a time */
4765         int j;
4766
4767         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4768         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4769
4770         for(j = destTop ; j < (srcHeight + destTop) ; j++){
4771
4772                 glTexSubImage2D(glDescription->target
4773                     ,glDescription->level
4774                     ,destLeft
4775                     ,j
4776                     ,srcWidth
4777                     ,1
4778                     ,glDescription->glFormat
4779                     ,glDescription->glType
4780                     ,data /* could be quicker using */
4781                 );
4782             data += rowoffset;
4783         }
4784
4785     } else { /* Full width, so just write out the whole texture */
4786
4787         if (WINED3DFMT_DXT1 == destFormat ||
4788             WINED3DFMT_DXT2 == destFormat ||
4789             WINED3DFMT_DXT3 == destFormat ||
4790             WINED3DFMT_DXT4 == destFormat ||
4791             WINED3DFMT_DXT5 == destFormat) {
4792             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4793                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4794                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
4795                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
4796                 } if (destFormat != srcFormat) {
4797                     FIXME("Updating mixed format compressed texture is not curretly support\n");
4798                 } else {
4799                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4800                                                         glDescription->level,
4801                                                         glDescription->glFormatInternal,
4802                                                         srcWidth,
4803                                                         srcHeight,
4804                                                         0,
4805                                                         destSize,
4806                                                         IWineD3DSurface_GetData(pSourceSurface));
4807                 }
4808             } else {
4809                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4810             }
4811
4812
4813         } else {
4814             glTexSubImage2D(glDescription->target
4815                     ,glDescription->level
4816                     ,destLeft
4817                     ,destTop
4818                     ,srcWidth
4819                     ,srcHeight
4820                     ,glDescription->glFormat
4821                     ,glDescription->glType
4822                     ,IWineD3DSurface_GetData(pSourceSurface)
4823                 );
4824         }
4825      }
4826     checkGLcall("glTexSubImage2D");
4827
4828     LEAVE_GL();
4829
4830     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
4831     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
4832
4833     return WINED3D_OK;
4834 }
4835
4836 /* Implementation details at http://developer.nvidia.com/attach/6494
4837 and
4838 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4839 hmm.. no longer supported use
4840 OpenGL evaluators or  tessellate surfaces within your application.
4841 */
4842
4843 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4844 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
4845     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4846     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
4847     FIXME("(%p) : Stub\n", This);
4848     return WINED3D_OK;
4849
4850 }
4851
4852 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4853 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
4854     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4855     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
4856     FIXME("(%p) : Stub\n", This);
4857     return WINED3D_OK;
4858 }
4859
4860 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4861     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4862     TRACE("(%p) Handle(%d)\n", This, Handle);
4863     FIXME("(%p) : Stub\n", This);
4864     return WINED3D_OK;
4865 }
4866
4867 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
4868     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4869     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
4870     DDBLTFX BltFx;
4871     TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
4872
4873     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
4874         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
4875         return WINED3DERR_INVALIDCALL;
4876     }
4877
4878     /* Just forward this to the DirectDraw blitting engine */
4879     memset(&BltFx, 0, sizeof(BltFx));
4880     BltFx.dwSize = sizeof(BltFx);
4881     BltFx.u5.dwFillColor = color;
4882     return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
4883 }
4884
4885 /* rendertarget and deptth stencil functions */
4886 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
4887     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4888
4889     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
4890         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
4891         return WINED3DERR_INVALIDCALL;
4892     }
4893
4894     *ppRenderTarget = This->render_targets[RenderTargetIndex];
4895     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4896     /* Note inc ref on returned surface */
4897     if(*ppRenderTarget != NULL)
4898         IWineD3DSurface_AddRef(*ppRenderTarget);
4899     return WINED3D_OK;
4900 }
4901
4902 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
4903     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4904     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
4905     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
4906     IWineD3DSwapChainImpl *Swapchain;
4907     HRESULT hr;
4908
4909     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
4910
4911     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
4912     if(hr != WINED3D_OK) {
4913         ERR("Can't get the swapchain\n");
4914         return hr;
4915     }
4916
4917     /* Make sure to release the swapchain */
4918     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
4919
4920     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
4921         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
4922         return WINED3DERR_INVALIDCALL;
4923     }
4924     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
4925         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
4926         return WINED3DERR_INVALIDCALL;
4927     }
4928
4929     if(Swapchain->frontBuffer != Front) {
4930         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
4931
4932         if(Swapchain->frontBuffer)
4933             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
4934         Swapchain->frontBuffer = Front;
4935
4936         if(Swapchain->frontBuffer) {
4937             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
4938         }
4939     }
4940
4941     if(Back && !Swapchain->backBuffer) {
4942         /* We need memory for the back buffer array - only one back buffer this way */
4943         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
4944         if(!Swapchain->backBuffer) {
4945             ERR("Out of memory\n");
4946             return E_OUTOFMEMORY;
4947         }
4948     }
4949
4950     if(Swapchain->backBuffer[0] != Back) {
4951         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
4952         ENTER_GL();
4953         if(!Swapchain->backBuffer[0]) {
4954             /* GL was told to draw to the front buffer at creation,
4955              * undo that
4956              */
4957             glDrawBuffer(GL_BACK);
4958             checkGLcall("glDrawBuffer(GL_BACK)");
4959             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
4960             Swapchain->presentParms.BackBufferCount = 1;
4961         } else if (!Back) {
4962             /* That makes problems - disable for now */
4963             /* glDrawBuffer(GL_FRONT); */
4964             checkGLcall("glDrawBuffer(GL_FRONT)");
4965             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
4966             Swapchain->presentParms.BackBufferCount = 0;
4967         }
4968         LEAVE_GL();
4969
4970         if(Swapchain->backBuffer[0])
4971             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
4972         Swapchain->backBuffer[0] = Back;
4973
4974         if(Swapchain->backBuffer[0]) {
4975             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
4976         } else {
4977             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
4978         }
4979
4980     }
4981
4982     return WINED3D_OK;
4983 }
4984
4985 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
4986     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4987     *ppZStencilSurface = This->depthStencilBuffer;
4988     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
4989
4990     if(*ppZStencilSurface != NULL) {
4991         /* Note inc ref on returned surface */
4992         IWineD3DSurface_AddRef(*ppZStencilSurface);
4993     }
4994     return WINED3D_OK;
4995 }
4996
4997 static void bind_fbo(IWineD3DDevice *iface) {
4998     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4999
5000     if (!This->fbo) {
5001         GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
5002         checkGLcall("glGenFramebuffersEXT()");
5003     }
5004     GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
5005     checkGLcall("glBindFramebuffer()");
5006 }
5007
5008 /* TODO: Handle stencil attachments */
5009 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5010     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5011     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5012
5013     This->depth_copy_state = WINED3D_DCS_NO_COPY;
5014
5015     bind_fbo(iface);
5016
5017     if (depth_stencil_impl) {
5018         GLenum texttarget, target;
5019         GLint old_binding = 0;
5020
5021         IWineD3DSurface_PreLoad(depth_stencil);
5022         texttarget = depth_stencil_impl->glDescription.target;
5023         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5024
5025         glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5026         glBindTexture(target, depth_stencil_impl->glDescription.textureName);
5027         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5028         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5029         glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5030         glBindTexture(target, old_binding);
5031
5032         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5033         checkGLcall("glFramebufferTexture2DEXT()");
5034     } else {
5035         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5036         checkGLcall("glFramebufferTexture2DEXT()");
5037     }
5038
5039     if (!This->render_offscreen) {
5040         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5041         checkGLcall("glBindFramebuffer()");
5042     }
5043 }
5044
5045 void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5046     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5047     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5048
5049     if (idx >= GL_LIMITS(buffers)) {
5050         ERR("%p : Trying to set render target %d, but only %d supported\n", This, idx, GL_LIMITS(buffers));
5051     }
5052
5053     bind_fbo(iface);
5054
5055     if (rtimpl) {
5056         GLenum texttarget, target;
5057         GLint old_binding = 0;
5058
5059         IWineD3DSurface_PreLoad(render_target);
5060         texttarget = rtimpl->glDescription.target;
5061         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5062
5063         glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5064         glBindTexture(target, rtimpl->glDescription.textureName);
5065         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5066         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5067         glBindTexture(target, old_binding);
5068
5069         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, rtimpl->glDescription.textureName, 0));
5070         checkGLcall("glFramebufferTexture2DEXT()");
5071
5072         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5073     } else {
5074         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5075         checkGLcall("glFramebufferTexture2DEXT()");
5076
5077         This->draw_buffers[idx] = GL_NONE;
5078     }
5079
5080     if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5081         GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5082         checkGLcall("glDrawBuffers()");
5083     }
5084
5085     if (!This->render_offscreen) {
5086         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5087         checkGLcall("glBindFramebuffer()");
5088     }
5089 }
5090
5091 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5092     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5093     WINED3DVIEWPORT viewport;
5094
5095     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5096
5097     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5098         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5099         return WINED3DERR_INVALIDCALL;
5100     }
5101
5102     /* MSDN says that null disables the render target
5103     but a device must always be associated with a render target
5104     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5105
5106     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5107     for more details
5108     */
5109     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5110         FIXME("Trying to set render target 0 to NULL\n");
5111         return WINED3DERR_INVALIDCALL;
5112     }
5113     if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5114         FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of WINED3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
5115         return WINED3DERR_INVALIDCALL;
5116     }
5117
5118     /* If we are trying to set what we already have, don't bother */
5119     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5120         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5121         return WINED3D_OK;
5122     }
5123     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5124     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5125     This->render_targets[RenderTargetIndex] = pRenderTarget;
5126
5127     /* Render target 0 is special */
5128     if(RenderTargetIndex == 0) {
5129         /* Finally, reset the viewport as the MSDN states. */
5130         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5131         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5132         viewport.X      = 0;
5133         viewport.Y      = 0;
5134         viewport.MaxZ   = 1.0f;
5135         viewport.MinZ   = 0.0f;
5136         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5137
5138         /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
5139          * ctx properly.
5140          * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
5141          * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
5142          */
5143         ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
5144     } else {
5145         /* We only get more than 1 render target with fbos, so no need to check the offscreen rendering method */
5146         set_render_target_fbo(iface, RenderTargetIndex, pRenderTarget);
5147     }
5148     return WINED3D_OK;
5149 }
5150
5151 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5152     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5153     HRESULT  hr = WINED3D_OK;
5154     IWineD3DSurface *tmp;
5155
5156     TRACE("(%p) Swapping z-buffer\n",This);
5157
5158     if (pNewZStencil == This->stencilBufferTarget) {
5159         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5160     } else {
5161         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5162         * depending on the renter target implementation being used.
5163         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5164         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5165         * stencil buffer and incure an extra memory overhead
5166          ******************************************************/
5167
5168         tmp = This->stencilBufferTarget;
5169         This->stencilBufferTarget = pNewZStencil;
5170         /* should we be calling the parent or the wined3d surface? */
5171         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5172         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5173         hr = WINED3D_OK;
5174
5175         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5176             set_depth_stencil_fbo(iface, pNewZStencil);
5177         }
5178     }
5179
5180     return hr;
5181 }
5182
5183 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5184                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5185     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5186     /* TODO: the use of Impl is deprecated. */
5187     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5188
5189     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5190
5191     /* some basic validation checks */
5192     if(This->cursorTexture) {
5193         ENTER_GL();
5194         glDeleteTextures(1, &This->cursorTexture);
5195         LEAVE_GL();
5196         This->cursorTexture = 0;
5197     }
5198
5199     if(pCursorBitmap) {
5200         /* MSDN: Cursor must be A8R8G8B8 */
5201         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5202             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5203             return WINED3DERR_INVALIDCALL;
5204         }
5205
5206         /* MSDN: Cursor must be smaller than the display mode */
5207         if(pSur->currentDesc.Width > This->ddraw_width ||
5208            pSur->currentDesc.Height > This->ddraw_height) {
5209             ERR("(%p) : Surface(%p) is %dx%d pixels, but screen res is %dx%d\n", This, pSur, pSur->currentDesc.Width, pSur->currentDesc.Height, This->ddraw_width, This->ddraw_height);
5210             return WINED3DERR_INVALIDCALL;
5211         }
5212
5213         /* TODO: MSDN: Cursor sizes must be a power of 2 */
5214         /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
5215          * Texture and Blitting code to draw the cursor
5216          */
5217         pSur->Flags |= SFLAG_FORCELOAD;
5218         IWineD3DSurface_PreLoad(pCursorBitmap);
5219         pSur->Flags &= ~SFLAG_FORCELOAD;
5220         /* Do not store the surface's pointer because the application may release
5221          * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
5222          * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
5223          */
5224         This->cursorTexture = pSur->glDescription.textureName;
5225         This->cursorWidth = pSur->currentDesc.Width;
5226         This->cursorHeight = pSur->currentDesc.Height;
5227         pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
5228     }
5229
5230     This->xHotSpot = XHotSpot;
5231     This->yHotSpot = YHotSpot;
5232     return WINED3D_OK;
5233 }
5234
5235 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5236     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5237     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5238
5239     This->xScreenSpace = XScreenSpace;
5240     This->yScreenSpace = YScreenSpace;
5241
5242     return;
5243
5244 }
5245
5246 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5247     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5248     BOOL oldVisible = This->bCursorVisible;
5249     POINT pt;
5250
5251     TRACE("(%p) : visible(%d)\n", This, bShow);
5252
5253     if(This->cursorTexture)
5254         This->bCursorVisible = bShow;
5255     /*
5256      * When ShowCursor is first called it should make the cursor appear at the OS's last
5257      * known cursor position.  Because of this, some applications just repetitively call
5258      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
5259      */
5260     GetCursorPos(&pt);
5261     This->xScreenSpace = pt.x;
5262     This->yScreenSpace = pt.y;
5263
5264     return oldVisible;
5265 }
5266
5267 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5268     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5269     TRACE("(%p) : state (%u)\n", This, This->state);
5270     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
5271     switch (This->state) {
5272     case WINED3D_OK:
5273         return WINED3D_OK;
5274     case WINED3DERR_DEVICELOST:
5275         {
5276             ResourceList *resourceList  = This->resources;
5277             while (NULL != resourceList) {
5278                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
5279                 return WINED3DERR_DEVICENOTRESET;
5280                 resourceList = resourceList->next;
5281             }
5282             return WINED3DERR_DEVICELOST;
5283         }
5284     case WINED3DERR_DRIVERINTERNALERROR:
5285         return WINED3DERR_DRIVERINTERNALERROR;
5286     }
5287
5288     /* Unknown state */
5289     return WINED3DERR_DRIVERINTERNALERROR;
5290 }
5291
5292
5293 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5294     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5295     /** FIXME: Resource tracking needs to be done,
5296     * The closes we can do to this is set the priorities of all managed textures low
5297     * and then reset them.
5298      ***********************************************************/
5299     FIXME("(%p) : stub\n", This);
5300     return WINED3D_OK;
5301 }
5302
5303 void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5304     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
5305
5306     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
5307     if(surface->Flags & SFLAG_DIBSECTION) {
5308         /* Release the DC */
5309         SelectObject(surface->hDC, surface->dib.holdbitmap);
5310         DeleteDC(surface->hDC);
5311         /* Release the DIB section */
5312         DeleteObject(surface->dib.DIBsection);
5313         surface->dib.bitmap_data = NULL;
5314         surface->resource.allocatedMemory = NULL;
5315         surface->Flags &= ~SFLAG_DIBSECTION;
5316     }
5317     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
5318     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
5319     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
5320         surface->pow2Width = pPresentationParameters->BackBufferWidth;
5321         surface->pow2Height = pPresentationParameters->BackBufferHeight;
5322     } else {
5323         surface->pow2Width = surface->pow2Height = 1;
5324         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
5325         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
5326     }
5327     if(surface->glDescription.textureName) {
5328         ENTER_GL();
5329         glDeleteTextures(1, &surface->glDescription.textureName);
5330         LEAVE_GL();
5331         surface->glDescription.textureName = 0;
5332     }
5333     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
5334        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
5335         surface->Flags |= SFLAG_NONPOW2;
5336     } else  {
5337         surface->Flags &= ~SFLAG_NONPOW2;
5338     }
5339     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
5340     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
5341 }
5342
5343 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5344     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5345     IWineD3DSwapChainImpl *swapchain;
5346     HRESULT hr;
5347     BOOL DisplayModeChanged = FALSE;
5348     WINED3DDISPLAYMODE mode;
5349     TRACE("(%p)\n", This);
5350
5351     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
5352     if(FAILED(hr)) {
5353         ERR("Failed to get the first implicit swapchain\n");
5354         return hr;
5355     }
5356
5357     /* Is it necessary to recreate the gl context? Actually every setting can be changed
5358      * on an existing gl context, so there's no real need for recreation.
5359      *
5360      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
5361      *
5362      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
5363      */
5364     TRACE("New params:\n");
5365     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
5366     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
5367     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
5368     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
5369     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
5370     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
5371     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
5372     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
5373     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
5374     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
5375     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
5376     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
5377     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
5378
5379     /* No special treatment of these parameters. Just store them */
5380     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
5381     swapchain->presentParms.Flags = pPresentationParameters->Flags;
5382     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
5383     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
5384
5385     /* What to do about these? */
5386     if(pPresentationParameters->BackBufferCount != 0 &&
5387         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
5388         ERR("Cannot change the back buffer count yet\n");
5389     }
5390     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
5391         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
5392         ERR("Cannot change the back buffer format yet\n");
5393     }
5394     if(pPresentationParameters->hDeviceWindow != NULL &&
5395         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
5396         ERR("Cannot change the device window yet\n");
5397     }
5398     if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
5399         ERR("What do do about a changed auto depth stencil parameter?\n");
5400     }
5401
5402     if(pPresentationParameters->Windowed) {
5403         mode.Width = swapchain->orig_width;
5404         mode.Height = swapchain->orig_height;
5405         mode.RefreshRate = 0;
5406         mode.Format = swapchain->presentParms.BackBufferFormat;
5407     } else {
5408         mode.Width = pPresentationParameters->BackBufferWidth;
5409         mode.Height = pPresentationParameters->BackBufferHeight;
5410         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
5411         mode.Format = swapchain->presentParms.BackBufferFormat;
5412     }
5413
5414     /* Should Width == 800 && Height == 0 set 800x600? */
5415     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
5416        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
5417         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
5418     {
5419         WINED3DVIEWPORT vp;
5420         int i;
5421
5422         vp.X = 0;
5423         vp.Y = 0;
5424         vp.Width = pPresentationParameters->BackBufferWidth;
5425         vp.Height = pPresentationParameters->BackBufferHeight;
5426         vp.MinZ = 0;
5427         vp.MaxZ = 1;
5428
5429         if(!pPresentationParameters->Windowed) {
5430             DisplayModeChanged = TRUE;
5431         }
5432         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
5433         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
5434
5435         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
5436         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
5437             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
5438         }
5439
5440         /* Now set the new viewport */
5441         IWineD3DDevice_SetViewport(iface, &vp);
5442     }
5443
5444     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
5445        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
5446         DisplayModeChanged) {
5447
5448         /* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */
5449         if(!pPresentationParameters->Windowed) {
5450             IWineD3DDevice_SetFullscreen(iface, TRUE);
5451         }
5452
5453         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
5454
5455         /* Switching out of fullscreen mode? First set the original res, then change the window */
5456         if(pPresentationParameters->Windowed) {
5457             IWineD3DDevice_SetFullscreen(iface, FALSE);
5458         }
5459         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
5460     }
5461
5462     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
5463     return WINED3D_OK;
5464 }
5465
5466 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5467     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5468     /** FIXME: always true at the moment **/
5469     if(!bEnableDialogs) {
5470         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5471     }
5472     return WINED3D_OK;
5473 }
5474
5475
5476 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
5477     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5478     TRACE("(%p) : pParameters %p\n", This, pParameters);
5479
5480     *pParameters = This->createParms;
5481     return WINED3D_OK;
5482 }
5483
5484 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
5485     IWineD3DSwapChain *swapchain;
5486     HRESULT hrc = WINED3D_OK;
5487
5488     TRACE("Relaying  to swapchain\n");
5489
5490     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5491         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
5492         IWineD3DSwapChain_Release(swapchain);
5493     }
5494     return;
5495 }
5496
5497 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
5498     IWineD3DSwapChain *swapchain;
5499     HRESULT hrc = WINED3D_OK;
5500
5501     TRACE("Relaying  to swapchain\n");
5502
5503     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5504         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5505         IWineD3DSwapChain_Release(swapchain);
5506     }
5507     return;
5508 }
5509
5510
5511 /** ********************************************************
5512 *   Notification functions
5513 ** ********************************************************/
5514 /** This function must be called in the release of a resource when ref == 0,
5515 * the contents of resource must still be correct,
5516 * any handels to other resource held by the caller must be closed
5517 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5518  *****************************************************/
5519 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5520     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5521     ResourceList* resourceList;
5522
5523     TRACE("(%p) : resource %p\n", This, resource);
5524 #if 0
5525     EnterCriticalSection(&resourceStoreCriticalSection);
5526 #endif
5527     /* add a new texture to the frot of the linked list */
5528     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5529     resourceList->resource = resource;
5530
5531     /* Get the old head */
5532     resourceList->next = This->resources;
5533
5534     This->resources = resourceList;
5535     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5536
5537 #if 0
5538     LeaveCriticalSection(&resourceStoreCriticalSection);
5539 #endif
5540     return;
5541 }
5542
5543 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5544     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5545     ResourceList* resourceList = NULL;
5546     ResourceList* previousResourceList = NULL;
5547     
5548     TRACE("(%p) : resource %p\n", This, resource);
5549
5550 #if 0
5551     EnterCriticalSection(&resourceStoreCriticalSection);
5552 #endif
5553     resourceList = This->resources;
5554
5555     while (resourceList != NULL) {
5556         if(resourceList->resource == resource) break;
5557         previousResourceList = resourceList;
5558         resourceList = resourceList->next;
5559     }
5560
5561     if (resourceList == NULL) {
5562         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5563 #if 0
5564         LeaveCriticalSection(&resourceStoreCriticalSection);
5565 #endif
5566         return;
5567     } else {
5568             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5569     }
5570     /* make sure we don't leave a hole in the list */
5571     if (previousResourceList != NULL) {
5572         previousResourceList->next = resourceList->next;
5573     } else {
5574         This->resources = resourceList->next;
5575     }
5576
5577 #if 0
5578     LeaveCriticalSection(&resourceStoreCriticalSection);
5579 #endif
5580     return;
5581 }
5582
5583
5584 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5585     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5586     int counter;
5587
5588     TRACE("(%p) : resource %p\n", This, resource);
5589     switch(IWineD3DResource_GetType(resource)){
5590         case WINED3DRTYPE_SURFACE:
5591         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
5592         break;
5593         case WINED3DRTYPE_TEXTURE:
5594         case WINED3DRTYPE_CUBETEXTURE:
5595         case WINED3DRTYPE_VOLUMETEXTURE:
5596                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
5597                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5598                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5599                         This->stateBlock->textures[counter] = NULL;
5600                     }
5601                     if (This->updateStateBlock != This->stateBlock ){
5602                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5603                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5604                             This->updateStateBlock->textures[counter] = NULL;
5605                         }
5606                     }
5607                 }
5608         break;
5609         case WINED3DRTYPE_VOLUME:
5610         /* TODO: nothing really? */
5611         break;
5612         case WINED3DRTYPE_VERTEXBUFFER:
5613         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5614         {
5615             int streamNumber;
5616             TRACE("Cleaning up stream pointers\n");
5617
5618             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5619                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5620                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5621                 */
5622                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5623                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5624                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5625                         This->updateStateBlock->streamSource[streamNumber] = 0;
5626                         /* Set changed flag? */
5627                     }
5628                 }
5629                 if (This->stateBlock != NULL ) { /* only happens if there is an error in the application, or on reset/release (because we don't manage internal tracking properly) */
5630                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5631                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5632                         This->stateBlock->streamSource[streamNumber] = 0;
5633                     }
5634                 }
5635 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5636                  else { /* This shouldn't happen */
5637                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5638                 }
5639 #endif
5640
5641             }
5642         }
5643         break;
5644         case WINED3DRTYPE_INDEXBUFFER:
5645         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5646         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5647             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5648                 This->updateStateBlock->pIndexData =  NULL;
5649             }
5650         }
5651         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5652             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5653                 This->stateBlock->pIndexData =  NULL;
5654             }
5655         }
5656
5657         break;
5658         default:
5659         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
5660         break;
5661     }
5662
5663
5664     /* Remove the resoruce from the resourceStore */
5665     IWineD3DDeviceImpl_RemoveResource(iface, resource);
5666
5667     TRACE("Resource released\n");
5668
5669 }
5670
5671 /**********************************************************
5672  * IWineD3DDevice VTbl follows
5673  **********************************************************/
5674
5675 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5676 {
5677     /*** IUnknown methods ***/
5678     IWineD3DDeviceImpl_QueryInterface,
5679     IWineD3DDeviceImpl_AddRef,
5680     IWineD3DDeviceImpl_Release,
5681     /*** IWineD3DDevice methods ***/
5682     IWineD3DDeviceImpl_GetParent,
5683     /*** Creation methods**/
5684     IWineD3DDeviceImpl_CreateVertexBuffer,
5685     IWineD3DDeviceImpl_CreateIndexBuffer,
5686     IWineD3DDeviceImpl_CreateStateBlock,
5687     IWineD3DDeviceImpl_CreateSurface,
5688     IWineD3DDeviceImpl_CreateTexture,
5689     IWineD3DDeviceImpl_CreateVolumeTexture,
5690     IWineD3DDeviceImpl_CreateVolume,
5691     IWineD3DDeviceImpl_CreateCubeTexture,
5692     IWineD3DDeviceImpl_CreateQuery,
5693     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5694     IWineD3DDeviceImpl_CreateVertexDeclaration,
5695     IWineD3DDeviceImpl_CreateVertexShader,
5696     IWineD3DDeviceImpl_CreatePixelShader,
5697     IWineD3DDeviceImpl_CreatePalette,
5698     /*** Odd functions **/
5699     IWineD3DDeviceImpl_Init3D,
5700     IWineD3DDeviceImpl_Uninit3D,
5701     IWineD3DDeviceImpl_SetFullscreen,
5702     IWineD3DDeviceImpl_EvictManagedResources,
5703     IWineD3DDeviceImpl_GetAvailableTextureMem,
5704     IWineD3DDeviceImpl_GetBackBuffer,
5705     IWineD3DDeviceImpl_GetCreationParameters,
5706     IWineD3DDeviceImpl_GetDeviceCaps,
5707     IWineD3DDeviceImpl_GetDirect3D,
5708     IWineD3DDeviceImpl_GetDisplayMode,
5709     IWineD3DDeviceImpl_SetDisplayMode,
5710     IWineD3DDeviceImpl_GetHWND,
5711     IWineD3DDeviceImpl_SetHWND,
5712     IWineD3DDeviceImpl_GetNumberOfSwapChains,
5713     IWineD3DDeviceImpl_GetRasterStatus,
5714     IWineD3DDeviceImpl_GetSwapChain,
5715     IWineD3DDeviceImpl_Reset,
5716     IWineD3DDeviceImpl_SetDialogBoxMode,
5717     IWineD3DDeviceImpl_SetCursorProperties,
5718     IWineD3DDeviceImpl_SetCursorPosition,
5719     IWineD3DDeviceImpl_ShowCursor,
5720     IWineD3DDeviceImpl_TestCooperativeLevel,
5721     /*** Getters and setters **/
5722     IWineD3DDeviceImpl_SetClipPlane,
5723     IWineD3DDeviceImpl_GetClipPlane,
5724     IWineD3DDeviceImpl_SetClipStatus,
5725     IWineD3DDeviceImpl_GetClipStatus,
5726     IWineD3DDeviceImpl_SetCurrentTexturePalette,
5727     IWineD3DDeviceImpl_GetCurrentTexturePalette,
5728     IWineD3DDeviceImpl_SetDepthStencilSurface,
5729     IWineD3DDeviceImpl_GetDepthStencilSurface,
5730     IWineD3DDeviceImpl_SetFVF,
5731     IWineD3DDeviceImpl_GetFVF,
5732     IWineD3DDeviceImpl_SetGammaRamp,
5733     IWineD3DDeviceImpl_GetGammaRamp,
5734     IWineD3DDeviceImpl_SetIndices,
5735     IWineD3DDeviceImpl_GetIndices,
5736     IWineD3DDeviceImpl_SetBasevertexIndex,
5737     IWineD3DDeviceImpl_SetLight,
5738     IWineD3DDeviceImpl_GetLight,
5739     IWineD3DDeviceImpl_SetLightEnable,
5740     IWineD3DDeviceImpl_GetLightEnable,
5741     IWineD3DDeviceImpl_SetMaterial,
5742     IWineD3DDeviceImpl_GetMaterial,
5743     IWineD3DDeviceImpl_SetNPatchMode,
5744     IWineD3DDeviceImpl_GetNPatchMode,
5745     IWineD3DDeviceImpl_SetPaletteEntries,
5746     IWineD3DDeviceImpl_GetPaletteEntries,
5747     IWineD3DDeviceImpl_SetPixelShader,
5748     IWineD3DDeviceImpl_GetPixelShader,
5749     IWineD3DDeviceImpl_SetPixelShaderConstantB,
5750     IWineD3DDeviceImpl_GetPixelShaderConstantB,
5751     IWineD3DDeviceImpl_SetPixelShaderConstantI,
5752     IWineD3DDeviceImpl_GetPixelShaderConstantI,
5753     IWineD3DDeviceImpl_SetPixelShaderConstantF,
5754     IWineD3DDeviceImpl_GetPixelShaderConstantF,
5755     IWineD3DDeviceImpl_SetRenderState,
5756     IWineD3DDeviceImpl_GetRenderState,
5757     IWineD3DDeviceImpl_SetRenderTarget,
5758     IWineD3DDeviceImpl_GetRenderTarget,
5759     IWineD3DDeviceImpl_SetFrontBackBuffers,
5760     IWineD3DDeviceImpl_SetSamplerState,
5761     IWineD3DDeviceImpl_GetSamplerState,
5762     IWineD3DDeviceImpl_SetScissorRect,
5763     IWineD3DDeviceImpl_GetScissorRect,
5764     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5765     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5766     IWineD3DDeviceImpl_SetStreamSource,
5767     IWineD3DDeviceImpl_GetStreamSource,
5768     IWineD3DDeviceImpl_SetStreamSourceFreq,
5769     IWineD3DDeviceImpl_GetStreamSourceFreq,
5770     IWineD3DDeviceImpl_SetTexture,
5771     IWineD3DDeviceImpl_GetTexture,
5772     IWineD3DDeviceImpl_SetTextureStageState,
5773     IWineD3DDeviceImpl_GetTextureStageState,
5774     IWineD3DDeviceImpl_SetTransform,
5775     IWineD3DDeviceImpl_GetTransform,
5776     IWineD3DDeviceImpl_SetVertexDeclaration,
5777     IWineD3DDeviceImpl_GetVertexDeclaration,
5778     IWineD3DDeviceImpl_SetVertexShader,
5779     IWineD3DDeviceImpl_GetVertexShader,
5780     IWineD3DDeviceImpl_SetVertexShaderConstantB,
5781     IWineD3DDeviceImpl_GetVertexShaderConstantB,
5782     IWineD3DDeviceImpl_SetVertexShaderConstantI,
5783     IWineD3DDeviceImpl_GetVertexShaderConstantI,
5784     IWineD3DDeviceImpl_SetVertexShaderConstantF,
5785     IWineD3DDeviceImpl_GetVertexShaderConstantF,
5786     IWineD3DDeviceImpl_SetViewport,
5787     IWineD3DDeviceImpl_GetViewport,
5788     IWineD3DDeviceImpl_MultiplyTransform,
5789     IWineD3DDeviceImpl_ValidateDevice,
5790     IWineD3DDeviceImpl_ProcessVertices,
5791     /*** State block ***/
5792     IWineD3DDeviceImpl_BeginStateBlock,
5793     IWineD3DDeviceImpl_EndStateBlock,
5794     /*** Scene management ***/
5795     IWineD3DDeviceImpl_BeginScene,
5796     IWineD3DDeviceImpl_EndScene,
5797     IWineD3DDeviceImpl_Present,
5798     IWineD3DDeviceImpl_Clear,
5799     /*** Drawing ***/
5800     IWineD3DDeviceImpl_DrawPrimitive,
5801     IWineD3DDeviceImpl_DrawIndexedPrimitive,
5802     IWineD3DDeviceImpl_DrawPrimitiveUP,
5803     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5804     IWineD3DDeviceImpl_DrawPrimitiveStrided,
5805     IWineD3DDeviceImpl_DrawRectPatch,
5806     IWineD3DDeviceImpl_DrawTriPatch,
5807     IWineD3DDeviceImpl_DeletePatch,
5808     IWineD3DDeviceImpl_ColorFill,
5809     IWineD3DDeviceImpl_UpdateTexture,
5810     IWineD3DDeviceImpl_UpdateSurface,
5811     IWineD3DDeviceImpl_GetFrontBufferData,
5812     /*** object tracking ***/
5813     IWineD3DDeviceImpl_ResourceReleased
5814 };
5815
5816
5817 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5818     WINED3DRS_ALPHABLENDENABLE   ,
5819     WINED3DRS_ALPHAFUNC          ,
5820     WINED3DRS_ALPHAREF           ,
5821     WINED3DRS_ALPHATESTENABLE    ,
5822     WINED3DRS_BLENDOP            ,
5823     WINED3DRS_COLORWRITEENABLE   ,
5824     WINED3DRS_DESTBLEND          ,
5825     WINED3DRS_DITHERENABLE       ,
5826     WINED3DRS_FILLMODE           ,
5827     WINED3DRS_FOGDENSITY         ,
5828     WINED3DRS_FOGEND             ,
5829     WINED3DRS_FOGSTART           ,
5830     WINED3DRS_LASTPIXEL          ,
5831     WINED3DRS_SHADEMODE          ,
5832     WINED3DRS_SRCBLEND           ,
5833     WINED3DRS_STENCILENABLE      ,
5834     WINED3DRS_STENCILFAIL        ,
5835     WINED3DRS_STENCILFUNC        ,
5836     WINED3DRS_STENCILMASK        ,
5837     WINED3DRS_STENCILPASS        ,
5838     WINED3DRS_STENCILREF         ,
5839     WINED3DRS_STENCILWRITEMASK   ,
5840     WINED3DRS_STENCILZFAIL       ,
5841     WINED3DRS_TEXTUREFACTOR      ,
5842     WINED3DRS_WRAP0              ,
5843     WINED3DRS_WRAP1              ,
5844     WINED3DRS_WRAP2              ,
5845     WINED3DRS_WRAP3              ,
5846     WINED3DRS_WRAP4              ,
5847     WINED3DRS_WRAP5              ,
5848     WINED3DRS_WRAP6              ,
5849     WINED3DRS_WRAP7              ,
5850     WINED3DRS_ZENABLE            ,
5851     WINED3DRS_ZFUNC              ,
5852     WINED3DRS_ZWRITEENABLE
5853 };
5854
5855 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5856     WINED3DTSS_ADDRESSW              ,
5857     WINED3DTSS_ALPHAARG0             ,
5858     WINED3DTSS_ALPHAARG1             ,
5859     WINED3DTSS_ALPHAARG2             ,
5860     WINED3DTSS_ALPHAOP               ,
5861     WINED3DTSS_BUMPENVLOFFSET        ,
5862     WINED3DTSS_BUMPENVLSCALE         ,
5863     WINED3DTSS_BUMPENVMAT00          ,
5864     WINED3DTSS_BUMPENVMAT01          ,
5865     WINED3DTSS_BUMPENVMAT10          ,
5866     WINED3DTSS_BUMPENVMAT11          ,
5867     WINED3DTSS_COLORARG0             ,
5868     WINED3DTSS_COLORARG1             ,
5869     WINED3DTSS_COLORARG2             ,
5870     WINED3DTSS_COLOROP               ,
5871     WINED3DTSS_RESULTARG             ,
5872     WINED3DTSS_TEXCOORDINDEX         ,
5873     WINED3DTSS_TEXTURETRANSFORMFLAGS
5874 };
5875
5876 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5877     WINED3DSAMP_ADDRESSU         ,
5878     WINED3DSAMP_ADDRESSV         ,
5879     WINED3DSAMP_ADDRESSW         ,
5880     WINED3DSAMP_BORDERCOLOR      ,
5881     WINED3DSAMP_MAGFILTER        ,
5882     WINED3DSAMP_MINFILTER        ,
5883     WINED3DSAMP_MIPFILTER        ,
5884     WINED3DSAMP_MIPMAPLODBIAS    ,
5885     WINED3DSAMP_MAXMIPLEVEL      ,
5886     WINED3DSAMP_MAXANISOTROPY    ,
5887     WINED3DSAMP_SRGBTEXTURE      ,
5888     WINED3DSAMP_ELEMENTINDEX
5889 };
5890
5891 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5892     WINED3DRS_AMBIENT                       ,
5893     WINED3DRS_AMBIENTMATERIALSOURCE         ,
5894     WINED3DRS_CLIPPING                      ,
5895     WINED3DRS_CLIPPLANEENABLE               ,
5896     WINED3DRS_COLORVERTEX                   ,
5897     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
5898     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
5899     WINED3DRS_FOGDENSITY                    ,
5900     WINED3DRS_FOGEND                        ,
5901     WINED3DRS_FOGSTART                      ,
5902     WINED3DRS_FOGTABLEMODE                  ,
5903     WINED3DRS_FOGVERTEXMODE                 ,
5904     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
5905     WINED3DRS_LIGHTING                      ,
5906     WINED3DRS_LOCALVIEWER                   ,
5907     WINED3DRS_MULTISAMPLEANTIALIAS          ,
5908     WINED3DRS_MULTISAMPLEMASK               ,
5909     WINED3DRS_NORMALIZENORMALS              ,
5910     WINED3DRS_PATCHEDGESTYLE                ,
5911     WINED3DRS_POINTSCALE_A                  ,
5912     WINED3DRS_POINTSCALE_B                  ,
5913     WINED3DRS_POINTSCALE_C                  ,
5914     WINED3DRS_POINTSCALEENABLE              ,
5915     WINED3DRS_POINTSIZE                     ,
5916     WINED3DRS_POINTSIZE_MAX                 ,
5917     WINED3DRS_POINTSIZE_MIN                 ,
5918     WINED3DRS_POINTSPRITEENABLE             ,
5919     WINED3DRS_RANGEFOGENABLE                ,
5920     WINED3DRS_SPECULARMATERIALSOURCE        ,
5921     WINED3DRS_TWEENFACTOR                   ,
5922     WINED3DRS_VERTEXBLEND
5923 };
5924
5925 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5926     WINED3DTSS_TEXCOORDINDEX         ,
5927     WINED3DTSS_TEXTURETRANSFORMFLAGS
5928 };
5929
5930 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5931     WINED3DSAMP_DMAPOFFSET
5932 };
5933
5934 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
5935     DWORD rep = StateTable[state].representative;
5936     DWORD idx;
5937     BYTE shift;
5938     UINT i;
5939     WineD3DContext *context;
5940
5941     if(!rep) return;
5942     for(i = 0; i < This->numContexts; i++) {
5943         context = This->contexts[i];
5944         if(isStateDirty(context, rep)) continue;
5945
5946         context->dirtyArray[context->numDirtyEntries++] = rep;
5947         idx = rep >> 5;
5948         shift = rep & 0x1f;
5949         context->isStateDirty[idx] |= (1 << shift);
5950     }
5951 }