janitorial: Remove two redundant checks for NULL.
[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     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     if(This->render_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4237         ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags |= SFLAG_INTEXTURE;
4238         ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags &= ~SFLAG_INSYSMEM;
4239     } else {
4240         ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags |= SFLAG_INDRAWABLE;
4241         ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INSYSMEM);
4242     }
4243     return WINED3D_OK;
4244 }
4245
4246 /*****
4247  * Drawing functions
4248  *****/
4249 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4250                                                 UINT PrimitiveCount) {
4251
4252     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4253     This->stateBlock->streamIsUP = FALSE;
4254
4255     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4256                                debug_d3dprimitivetype(PrimitiveType),
4257                                StartVertex, PrimitiveCount);
4258
4259     if(This->stateBlock->loadBaseVertexIndex != 0) {
4260         This->stateBlock->loadBaseVertexIndex = 0;
4261         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4262     }
4263     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4264     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4265                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4266     return WINED3D_OK;
4267 }
4268
4269 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4270 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4271                                                            WINED3DPRIMITIVETYPE PrimitiveType,
4272                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4273
4274     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4275     UINT                 idxStride = 2;
4276     IWineD3DIndexBuffer *pIB;
4277     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
4278     GLuint vbo;
4279
4280     pIB = This->stateBlock->pIndexData;
4281     This->stateBlock->streamIsUP = FALSE;
4282     vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
4283
4284     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
4285           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4286           minIndex, NumVertices, startIndex, primCount);
4287
4288     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4289     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4290         idxStride = 2;
4291     } else {
4292         idxStride = 4;
4293     }
4294
4295     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4296         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4297         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4298     }
4299
4300     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
4301                    idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4302
4303     return WINED3D_OK;
4304 }
4305
4306 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4307                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4308                                                     UINT VertexStreamZeroStride) {
4309     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4310
4311     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4312              debug_d3dprimitivetype(PrimitiveType),
4313              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4314
4315     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4316     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4317     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4318     This->stateBlock->streamIsUP = TRUE;
4319     This->stateBlock->loadBaseVertexIndex = 0;
4320
4321     /* TODO: Only mark dirty if drawing from a different UP address */
4322     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4323
4324     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4325                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4326
4327     /* MSDN specifies stream zero settings must be set to NULL */
4328     This->stateBlock->streamStride[0] = 0;
4329     This->stateBlock->streamSource[0] = NULL;
4330
4331     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4332      * the new stream sources or use UP drawing again
4333      */
4334     return WINED3D_OK;
4335 }
4336
4337 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4338                                                              UINT MinVertexIndex, UINT NumVertices,
4339                                                              UINT PrimitiveCount, CONST void* pIndexData,
4340                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4341                                                              UINT VertexStreamZeroStride) {
4342     int                 idxStride;
4343     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4344
4345     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4346              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4347              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4348              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4349
4350     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4351         idxStride = 2;
4352     } else {
4353         idxStride = 4;
4354     }
4355
4356     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4357     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4358     This->stateBlock->streamIsUP = TRUE;
4359     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4360
4361     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4362     This->stateBlock->baseVertexIndex = 0;
4363     This->stateBlock->loadBaseVertexIndex = 0;
4364     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4365     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4366     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4367
4368     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4369
4370     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4371     This->stateBlock->streamSource[0] = NULL;
4372     This->stateBlock->streamStride[0] = 0;
4373     This->stateBlock->pIndexData = NULL;
4374     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4375      * SetStreamSource to specify a vertex buffer
4376      */
4377
4378     return WINED3D_OK;
4379 }
4380
4381 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4382     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4383
4384     /* Mark the state dirty until we have nicer tracking
4385      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4386      * that value.
4387      */
4388     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4389     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4390     This->stateBlock->baseVertexIndex = 0;
4391     This->up_strided = DrawPrimStrideData;
4392     This->stateBlock->streamIsUP = TRUE;
4393     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
4394     This->up_strided = NULL;
4395     return WINED3D_OK;
4396 }
4397  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4398 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4399     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4400     HRESULT hr = WINED3D_OK;
4401     WINED3DRESOURCETYPE sourceType;
4402     WINED3DRESOURCETYPE destinationType;
4403     int i ,levels;
4404
4405     /* TODO: think about moving the code into IWineD3DBaseTexture  */
4406
4407     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4408
4409     /* verify that the source and destination textures aren't NULL */
4410     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4411         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4412              This, pSourceTexture, pDestinationTexture);
4413         hr = WINED3DERR_INVALIDCALL;
4414     }
4415
4416     if (pSourceTexture == pDestinationTexture) {
4417         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4418              This, pSourceTexture, pDestinationTexture);
4419         hr = WINED3DERR_INVALIDCALL;
4420     }
4421     /* Verify that the source and destination textures are the same type */
4422     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
4423     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4424
4425     if (sourceType != destinationType) {
4426         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
4427              This);
4428         hr = WINED3DERR_INVALIDCALL;
4429     }
4430
4431     /* check that both textures have the identical numbers of levels  */
4432     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4433         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4434         hr = WINED3DERR_INVALIDCALL;
4435     }
4436
4437     if (WINED3D_OK == hr) {
4438
4439         /* Make sure that the destination texture is loaded */
4440         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4441
4442         /* Update every surface level of the texture */
4443         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4444
4445         switch (sourceType) {
4446         case WINED3DRTYPE_TEXTURE:
4447             {
4448                 IWineD3DSurface *srcSurface;
4449                 IWineD3DSurface *destSurface;
4450
4451                 for (i = 0 ; i < levels ; ++i) {
4452                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
4453                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4454                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4455                     IWineD3DSurface_Release(srcSurface);
4456                     IWineD3DSurface_Release(destSurface);
4457                     if (WINED3D_OK != hr) {
4458                         WARN("(%p) : Call to update surface failed\n", This);
4459                         return hr;
4460                     }
4461                 }
4462             }
4463             break;
4464         case WINED3DRTYPE_CUBETEXTURE:
4465             {
4466                 IWineD3DSurface *srcSurface;
4467                 IWineD3DSurface *destSurface;
4468                 WINED3DCUBEMAP_FACES faceType;
4469
4470                 for (i = 0 ; i < levels ; ++i) {
4471                     /* Update each cube face */
4472                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4473                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
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 srcSurface %p\n", srcSurface);
4478                         }
4479                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4480                         if (WINED3D_OK != hr) {
4481                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4482                         } else {
4483                             TRACE("Got desrSurface %p\n", destSurface);
4484                         }
4485                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4486                         IWineD3DSurface_Release(srcSurface);
4487                         IWineD3DSurface_Release(destSurface);
4488                         if (WINED3D_OK != hr) {
4489                             WARN("(%p) : Call to update surface failed\n", This);
4490                             return hr;
4491                         }
4492                     }
4493                 }
4494             }
4495             break;
4496 #if 0 /* TODO: Add support for volume textures */
4497         case WINED3DRTYPE_VOLUMETEXTURE:
4498             {
4499                 IWineD3DVolume  srcVolume  = NULL;
4500                 IWineD3DSurface destVolume = NULL;
4501
4502                 for (i = 0 ; i < levels ; ++i) {
4503                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
4504                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4505                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4506                     IWineD3DVolume_Release(srcSurface);
4507                     IWineD3DVolume_Release(destSurface);
4508                     if (WINED3D_OK != hr) {
4509                         WARN("(%p) : Call to update volume failed\n", This);
4510                         return hr;
4511                     }
4512                 }
4513             }
4514             break;
4515 #endif
4516         default:
4517             FIXME("(%p) : Unsupported source and destination type\n", This);
4518             hr = WINED3DERR_INVALIDCALL;
4519         }
4520     }
4521
4522     return hr;
4523 }
4524
4525 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4526     IWineD3DSwapChain *swapChain;
4527     HRESULT hr;
4528     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4529     if(hr == WINED3D_OK) {
4530         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4531                 IWineD3DSwapChain_Release(swapChain);
4532     }
4533     return hr;
4534 }
4535
4536 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4537     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4538     /* return a sensible default */
4539     *pNumPasses = 1;
4540     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
4541     FIXME("(%p) : stub\n", This);
4542     return WINED3D_OK;
4543 }
4544
4545 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4546     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4547     int j;
4548     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4549     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4550         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4551         return WINED3DERR_INVALIDCALL;
4552     }
4553     for (j = 0; j < 256; ++j) {
4554         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
4555         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4556         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
4557         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4558     }
4559     TRACE("(%p) : returning\n", This);
4560     return WINED3D_OK;
4561 }
4562
4563 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4564     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4565     int j;
4566     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4567     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4568         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4569         return WINED3DERR_INVALIDCALL;
4570     }
4571     for (j = 0; j < 256; ++j) {
4572         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
4573         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4574         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
4575         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4576     }
4577     TRACE("(%p) : returning\n", This);
4578     return WINED3D_OK;
4579 }
4580
4581 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4582     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4583     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4584     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4585         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4586         return WINED3DERR_INVALIDCALL;
4587     }
4588     /*TODO: stateblocks */
4589     This->currentPalette = PaletteNumber;
4590     TRACE("(%p) : returning\n", This);
4591     return WINED3D_OK;
4592 }
4593
4594 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4595     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4596     if (PaletteNumber == NULL) {
4597         WARN("(%p) : returning Invalid Call\n", This);
4598         return WINED3DERR_INVALIDCALL;
4599     }
4600     /*TODO: stateblocks */
4601     *PaletteNumber = This->currentPalette;
4602     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
4603     return WINED3D_OK;
4604 }
4605
4606 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4607     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4608     static BOOL showFixmes = TRUE;
4609     if (showFixmes) {
4610         FIXME("(%p) : stub\n", This);
4611         showFixmes = FALSE;
4612     }
4613
4614     This->softwareVertexProcessing = bSoftware;
4615     return WINED3D_OK;
4616 }
4617
4618
4619 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4620     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4621     static BOOL showFixmes = TRUE;
4622     if (showFixmes) {
4623         FIXME("(%p) : stub\n", This);
4624         showFixmes = FALSE;
4625     }
4626     return This->softwareVertexProcessing;
4627 }
4628
4629
4630 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
4631     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4632     IWineD3DSwapChain *swapChain;
4633     HRESULT hr;
4634
4635     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4636
4637     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4638     if(hr == WINED3D_OK){
4639         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4640         IWineD3DSwapChain_Release(swapChain);
4641     }else{
4642         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
4643     }
4644     return hr;
4645 }
4646
4647
4648 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4649     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4650     static BOOL showfixmes = TRUE;
4651     if(nSegments != 0.0f) {
4652         if( showfixmes) {
4653             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4654             showfixmes = FALSE;
4655         }
4656     }
4657     return WINED3D_OK;
4658 }
4659
4660 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4661     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4662     static BOOL showfixmes = TRUE;
4663     if( showfixmes) {
4664         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4665         showfixmes = FALSE;
4666     }
4667     return 0.0f;
4668 }
4669
4670 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4671     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
4672     /** TODO: remove casts to IWineD3DSurfaceImpl
4673      *       NOTE: move code to surface to accomplish this
4674       ****************************************/
4675     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
4676     int srcWidth, srcHeight;
4677     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4678     WINED3DFORMAT destFormat, srcFormat;
4679     UINT          destSize;
4680     int srcLeft, destLeft, destTop;
4681     WINED3DPOOL       srcPool, destPool;
4682     int offset    = 0;
4683     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4684     glDescriptor *glDescription = NULL;
4685
4686     WINED3DSURFACE_DESC  winedesc;
4687
4688     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
4689     memset(&winedesc, 0, sizeof(winedesc));
4690     winedesc.Width  = &srcSurfaceWidth;
4691     winedesc.Height = &srcSurfaceHeight;
4692     winedesc.Pool   = &srcPool;
4693     winedesc.Format = &srcFormat;
4694
4695     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4696
4697     winedesc.Width  = &destSurfaceWidth;
4698     winedesc.Height = &destSurfaceHeight;
4699     winedesc.Pool   = &destPool;
4700     winedesc.Format = &destFormat;
4701     winedesc.Size   = &destSize;
4702
4703     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4704
4705     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
4706         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
4707         return WINED3DERR_INVALIDCALL;
4708     }
4709
4710     if (destFormat == WINED3DFMT_UNKNOWN) {
4711         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
4712         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
4713
4714         /* Get the update surface description */
4715         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4716     }
4717
4718     ENTER_GL();
4719     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4720         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
4721         checkGLcall("glActiveTextureARB");
4722     }
4723
4724     /* Make sure the surface is loaded and up to date */
4725     IWineD3DSurface_PreLoad(pDestinationSurface);
4726
4727     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4728
4729     /* this needs to be done in lines if the sourceRect != the sourceWidth */
4730     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
4731     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
4732     srcLeft    = pSourceRect ? pSourceRect->left : 0;
4733     destLeft   = pDestPoint  ? pDestPoint->x : 0;
4734     destTop    = pDestPoint  ? pDestPoint->y : 0;
4735
4736
4737     /* This function doesn't support compressed textures
4738     the pitch is just bytesPerPixel * width */
4739     if(srcWidth != srcSurfaceWidth  || srcLeft ){
4740         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4741         offset   += srcLeft * pSrcSurface->bytesPerPixel;
4742         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4743     }
4744     /* TODO DXT formats */
4745
4746     if(pSourceRect != NULL && pSourceRect->top != 0){
4747        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4748     }
4749     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4750     ,This
4751     ,glDescription->level
4752     ,destLeft
4753     ,destTop
4754     ,srcWidth
4755     ,srcHeight
4756     ,glDescription->glFormat
4757     ,glDescription->glType
4758     ,IWineD3DSurface_GetData(pSourceSurface)
4759     );
4760
4761     /* Sanity check */
4762     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4763
4764         /* need to lock the surface to get the data */
4765         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4766     }
4767
4768     /* TODO: Cube and volume support */
4769     if(rowoffset != 0){
4770         /* not a whole row so we have to do it a line at a time */
4771         int j;
4772
4773         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4774         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4775
4776         for(j = destTop ; j < (srcHeight + destTop) ; j++){
4777
4778                 glTexSubImage2D(glDescription->target
4779                     ,glDescription->level
4780                     ,destLeft
4781                     ,j
4782                     ,srcWidth
4783                     ,1
4784                     ,glDescription->glFormat
4785                     ,glDescription->glType
4786                     ,data /* could be quicker using */
4787                 );
4788             data += rowoffset;
4789         }
4790
4791     } else { /* Full width, so just write out the whole texture */
4792
4793         if (WINED3DFMT_DXT1 == destFormat ||
4794             WINED3DFMT_DXT2 == destFormat ||
4795             WINED3DFMT_DXT3 == destFormat ||
4796             WINED3DFMT_DXT4 == destFormat ||
4797             WINED3DFMT_DXT5 == destFormat) {
4798             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4799                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4800                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
4801                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
4802                 } if (destFormat != srcFormat) {
4803                     FIXME("Updating mixed format compressed texture is not curretly support\n");
4804                 } else {
4805                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4806                                                         glDescription->level,
4807                                                         glDescription->glFormatInternal,
4808                                                         srcWidth,
4809                                                         srcHeight,
4810                                                         0,
4811                                                         destSize,
4812                                                         IWineD3DSurface_GetData(pSourceSurface));
4813                 }
4814             } else {
4815                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4816             }
4817
4818
4819         } else {
4820             glTexSubImage2D(glDescription->target
4821                     ,glDescription->level
4822                     ,destLeft
4823                     ,destTop
4824                     ,srcWidth
4825                     ,srcHeight
4826                     ,glDescription->glFormat
4827                     ,glDescription->glType
4828                     ,IWineD3DSurface_GetData(pSourceSurface)
4829                 );
4830         }
4831      }
4832     checkGLcall("glTexSubImage2D");
4833
4834     LEAVE_GL();
4835
4836     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags &= ~SFLAG_INSYSMEM;
4837     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_INTEXTURE;
4838     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
4839
4840     return WINED3D_OK;
4841 }
4842
4843 /* Implementation details at http://developer.nvidia.com/attach/6494
4844 and
4845 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4846 hmm.. no longer supported use
4847 OpenGL evaluators or  tessellate surfaces within your application.
4848 */
4849
4850 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4851 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
4852     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4853     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
4854     FIXME("(%p) : Stub\n", This);
4855     return WINED3D_OK;
4856
4857 }
4858
4859 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4860 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
4861     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4862     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
4863     FIXME("(%p) : Stub\n", This);
4864     return WINED3D_OK;
4865 }
4866
4867 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4868     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4869     TRACE("(%p) Handle(%d)\n", This, Handle);
4870     FIXME("(%p) : Stub\n", This);
4871     return WINED3D_OK;
4872 }
4873
4874 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
4875     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4876     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
4877     DDBLTFX BltFx;
4878     TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
4879
4880     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
4881         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
4882         return WINED3DERR_INVALIDCALL;
4883     }
4884
4885     /* Just forward this to the DirectDraw blitting engine */
4886     memset(&BltFx, 0, sizeof(BltFx));
4887     BltFx.dwSize = sizeof(BltFx);
4888     BltFx.u5.dwFillColor = color;
4889     return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
4890 }
4891
4892 /* rendertarget and deptth stencil functions */
4893 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
4894     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4895
4896     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
4897         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
4898         return WINED3DERR_INVALIDCALL;
4899     }
4900
4901     *ppRenderTarget = This->render_targets[RenderTargetIndex];
4902     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4903     /* Note inc ref on returned surface */
4904     if(*ppRenderTarget != NULL)
4905         IWineD3DSurface_AddRef(*ppRenderTarget);
4906     return WINED3D_OK;
4907 }
4908
4909 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
4910     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4911     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
4912     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
4913     IWineD3DSwapChainImpl *Swapchain;
4914     HRESULT hr;
4915
4916     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
4917
4918     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
4919     if(hr != WINED3D_OK) {
4920         ERR("Can't get the swapchain\n");
4921         return hr;
4922     }
4923
4924     /* Make sure to release the swapchain */
4925     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
4926
4927     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
4928         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
4929         return WINED3DERR_INVALIDCALL;
4930     }
4931     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
4932         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
4933         return WINED3DERR_INVALIDCALL;
4934     }
4935
4936     if(Swapchain->frontBuffer != Front) {
4937         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
4938
4939         if(Swapchain->frontBuffer)
4940             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
4941         Swapchain->frontBuffer = Front;
4942
4943         if(Swapchain->frontBuffer) {
4944             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
4945         }
4946     }
4947
4948     if(Back && !Swapchain->backBuffer) {
4949         /* We need memory for the back buffer array - only one back buffer this way */
4950         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
4951         if(!Swapchain->backBuffer) {
4952             ERR("Out of memory\n");
4953             return E_OUTOFMEMORY;
4954         }
4955     }
4956
4957     if(Swapchain->backBuffer[0] != Back) {
4958         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
4959         ENTER_GL();
4960         if(!Swapchain->backBuffer[0]) {
4961             /* GL was told to draw to the front buffer at creation,
4962              * undo that
4963              */
4964             glDrawBuffer(GL_BACK);
4965             checkGLcall("glDrawBuffer(GL_BACK)");
4966             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
4967             Swapchain->presentParms.BackBufferCount = 1;
4968         } else if (!Back) {
4969             /* That makes problems - disable for now */
4970             /* glDrawBuffer(GL_FRONT); */
4971             checkGLcall("glDrawBuffer(GL_FRONT)");
4972             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
4973             Swapchain->presentParms.BackBufferCount = 0;
4974         }
4975         LEAVE_GL();
4976
4977         if(Swapchain->backBuffer[0])
4978             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
4979         Swapchain->backBuffer[0] = Back;
4980
4981         if(Swapchain->backBuffer[0]) {
4982             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
4983         } else {
4984             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
4985         }
4986
4987     }
4988
4989     return WINED3D_OK;
4990 }
4991
4992 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
4993     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4994     *ppZStencilSurface = This->depthStencilBuffer;
4995     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
4996
4997     if(*ppZStencilSurface != NULL) {
4998         /* Note inc ref on returned surface */
4999         IWineD3DSurface_AddRef(*ppZStencilSurface);
5000     }
5001     return WINED3D_OK;
5002 }
5003
5004 static void bind_fbo(IWineD3DDevice *iface) {
5005     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5006
5007     if (!This->fbo) {
5008         GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
5009         checkGLcall("glGenFramebuffersEXT()");
5010     }
5011     GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
5012     checkGLcall("glBindFramebuffer()");
5013 }
5014
5015 /* TODO: Handle stencil attachments */
5016 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5017     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5018     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5019
5020     This->depth_copy_state = WINED3D_DCS_NO_COPY;
5021
5022     bind_fbo(iface);
5023
5024     if (depth_stencil_impl) {
5025         GLenum texttarget, target;
5026         GLint old_binding = 0;
5027
5028         IWineD3DSurface_PreLoad(depth_stencil);
5029         texttarget = depth_stencil_impl->glDescription.target;
5030         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5031
5032         glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5033         glBindTexture(target, depth_stencil_impl->glDescription.textureName);
5034         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5035         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5036         glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5037         glBindTexture(target, old_binding);
5038
5039         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5040         checkGLcall("glFramebufferTexture2DEXT()");
5041     } else {
5042         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5043         checkGLcall("glFramebufferTexture2DEXT()");
5044     }
5045
5046     if (!This->render_offscreen) {
5047         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5048         checkGLcall("glBindFramebuffer()");
5049     }
5050 }
5051
5052 void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5053     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5054     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5055
5056     if (idx >= GL_LIMITS(buffers)) {
5057         ERR("%p : Trying to set render target %d, but only %d supported\n", This, idx, GL_LIMITS(buffers));
5058     }
5059
5060     bind_fbo(iface);
5061
5062     if (rtimpl) {
5063         GLenum texttarget, target;
5064         GLint old_binding = 0;
5065
5066         IWineD3DSurface_PreLoad(render_target);
5067         texttarget = rtimpl->glDescription.target;
5068         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5069
5070         glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5071         glBindTexture(target, rtimpl->glDescription.textureName);
5072         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5073         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5074         glBindTexture(target, old_binding);
5075
5076         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, rtimpl->glDescription.textureName, 0));
5077         checkGLcall("glFramebufferTexture2DEXT()");
5078
5079         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5080     } else {
5081         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5082         checkGLcall("glFramebufferTexture2DEXT()");
5083
5084         This->draw_buffers[idx] = GL_NONE;
5085     }
5086
5087     if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5088         GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5089         checkGLcall("glDrawBuffers()");
5090     }
5091
5092     if (!This->render_offscreen) {
5093         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5094         checkGLcall("glBindFramebuffer()");
5095     }
5096 }
5097
5098 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5099     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5100     WINED3DVIEWPORT viewport;
5101
5102     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5103
5104     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5105         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5106         return WINED3DERR_INVALIDCALL;
5107     }
5108
5109     /* MSDN says that null disables the render target
5110     but a device must always be associated with a render target
5111     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5112
5113     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5114     for more details
5115     */
5116     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5117         FIXME("Trying to set render target 0 to NULL\n");
5118         return WINED3DERR_INVALIDCALL;
5119     }
5120     if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5121         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);
5122         return WINED3DERR_INVALIDCALL;
5123     }
5124
5125     /* If we are trying to set what we already have, don't bother */
5126     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5127         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5128         return WINED3D_OK;
5129     }
5130     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5131     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5132     This->render_targets[RenderTargetIndex] = pRenderTarget;
5133
5134     /* Render target 0 is special */
5135     if(RenderTargetIndex == 0) {
5136         /* Finally, reset the viewport as the MSDN states. */
5137         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5138         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5139         viewport.X      = 0;
5140         viewport.Y      = 0;
5141         viewport.MaxZ   = 1.0f;
5142         viewport.MinZ   = 0.0f;
5143         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5144         /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
5145          * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
5146          */
5147         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
5148
5149         /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
5150          * ctx properly.
5151          * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
5152          * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
5153          */
5154         ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
5155     } else {
5156         /* We only get more than 1 render target with fbos, so no need to check the offscreen rendering method */
5157         set_render_target_fbo(iface, RenderTargetIndex, pRenderTarget);
5158     }
5159     return WINED3D_OK;
5160 }
5161
5162 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5163     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5164     HRESULT  hr = WINED3D_OK;
5165     IWineD3DSurface *tmp;
5166
5167     TRACE("(%p) Swapping z-buffer\n",This);
5168
5169     if (pNewZStencil == This->stencilBufferTarget) {
5170         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5171     } else {
5172         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5173         * depending on the renter target implementation being used.
5174         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5175         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5176         * stencil buffer and incure an extra memory overhead
5177          ******************************************************/
5178
5179         tmp = This->stencilBufferTarget;
5180         This->stencilBufferTarget = pNewZStencil;
5181         /* should we be calling the parent or the wined3d surface? */
5182         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5183         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5184         hr = WINED3D_OK;
5185
5186         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5187             set_depth_stencil_fbo(iface, pNewZStencil);
5188         }
5189
5190         if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
5191             /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5192             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
5193             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
5194             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
5195         }
5196     }
5197
5198     return hr;
5199 }
5200
5201 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5202                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5203     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5204     /* TODO: the use of Impl is deprecated. */
5205     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5206
5207     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5208
5209     /* some basic validation checks */
5210     if(This->cursorTexture) {
5211         ENTER_GL();
5212         glDeleteTextures(1, &This->cursorTexture);
5213         LEAVE_GL();
5214         This->cursorTexture = 0;
5215     }
5216
5217     if(pCursorBitmap) {
5218         /* MSDN: Cursor must be A8R8G8B8 */
5219         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5220             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5221             return WINED3DERR_INVALIDCALL;
5222         }
5223
5224         /* MSDN: Cursor must be smaller than the display mode */
5225         if(pSur->currentDesc.Width > This->ddraw_width ||
5226            pSur->currentDesc.Height > This->ddraw_height) {
5227             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);
5228             return WINED3DERR_INVALIDCALL;
5229         }
5230
5231         /* TODO: MSDN: Cursor sizes must be a power of 2 */
5232         /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
5233          * Texture and Blitting code to draw the cursor
5234          */
5235         pSur->Flags |= SFLAG_FORCELOAD;
5236         IWineD3DSurface_PreLoad(pCursorBitmap);
5237         pSur->Flags &= ~SFLAG_FORCELOAD;
5238         /* Do not store the surface's pointer because the application may release
5239          * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
5240          * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
5241          */
5242         This->cursorTexture = pSur->glDescription.textureName;
5243         This->cursorWidth = pSur->currentDesc.Width;
5244         This->cursorHeight = pSur->currentDesc.Height;
5245         pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
5246     }
5247
5248     This->xHotSpot = XHotSpot;
5249     This->yHotSpot = YHotSpot;
5250     return WINED3D_OK;
5251 }
5252
5253 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5254     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5255     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5256
5257     This->xScreenSpace = XScreenSpace;
5258     This->yScreenSpace = YScreenSpace;
5259
5260     return;
5261
5262 }
5263
5264 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5265     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5266     BOOL oldVisible = This->bCursorVisible;
5267     POINT pt;
5268
5269     TRACE("(%p) : visible(%d)\n", This, bShow);
5270
5271     if(This->cursorTexture)
5272         This->bCursorVisible = bShow;
5273     /*
5274      * When ShowCursor is first called it should make the cursor appear at the OS's last
5275      * known cursor position.  Because of this, some applications just repetitively call
5276      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
5277      */
5278     GetCursorPos(&pt);
5279     This->xScreenSpace = pt.x;
5280     This->yScreenSpace = pt.y;
5281
5282     return oldVisible;
5283 }
5284
5285 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5286     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5287     TRACE("(%p) : state (%u)\n", This, This->state);
5288     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
5289     switch (This->state) {
5290     case WINED3D_OK:
5291         return WINED3D_OK;
5292     case WINED3DERR_DEVICELOST:
5293         {
5294             ResourceList *resourceList  = This->resources;
5295             while (NULL != resourceList) {
5296                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
5297                 return WINED3DERR_DEVICENOTRESET;
5298                 resourceList = resourceList->next;
5299             }
5300             return WINED3DERR_DEVICELOST;
5301         }
5302     case WINED3DERR_DRIVERINTERNALERROR:
5303         return WINED3DERR_DRIVERINTERNALERROR;
5304     }
5305
5306     /* Unknown state */
5307     return WINED3DERR_DRIVERINTERNALERROR;
5308 }
5309
5310
5311 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5312     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5313     /** FIXME: Resource tracking needs to be done,
5314     * The closes we can do to this is set the priorities of all managed textures low
5315     * and then reset them.
5316      ***********************************************************/
5317     FIXME("(%p) : stub\n", This);
5318     return WINED3D_OK;
5319 }
5320
5321 void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5322     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
5323
5324     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
5325     if(surface->Flags & SFLAG_DIBSECTION) {
5326         /* Release the DC */
5327         SelectObject(surface->hDC, surface->dib.holdbitmap);
5328         DeleteDC(surface->hDC);
5329         /* Release the DIB section */
5330         DeleteObject(surface->dib.DIBsection);
5331         surface->dib.bitmap_data = NULL;
5332         surface->resource.allocatedMemory = NULL;
5333         surface->Flags &= ~SFLAG_DIBSECTION;
5334     }
5335     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
5336     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
5337     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
5338         surface->pow2Width = pPresentationParameters->BackBufferWidth;
5339         surface->pow2Height = pPresentationParameters->BackBufferHeight;
5340     } else {
5341         surface->pow2Width = surface->pow2Height = 1;
5342         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
5343         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
5344     }
5345     if(surface->glDescription.textureName) {
5346         ENTER_GL();
5347         glDeleteTextures(1, &surface->glDescription.textureName);
5348         LEAVE_GL();
5349         surface->glDescription.textureName = 0;
5350     }
5351     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
5352        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
5353         surface->Flags |= SFLAG_NONPOW2;
5354     } else  {
5355         surface->Flags &= ~SFLAG_NONPOW2;
5356     }
5357     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
5358     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
5359 }
5360
5361 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5362     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5363     IWineD3DSwapChainImpl *swapchain;
5364     HRESULT hr;
5365     BOOL DisplayModeChanged = FALSE;
5366     WINED3DDISPLAYMODE mode;
5367     TRACE("(%p)\n", This);
5368
5369     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
5370     if(FAILED(hr)) {
5371         ERR("Failed to get the first implicit swapchain\n");
5372         return hr;
5373     }
5374
5375     /* Is it necessary to recreate the gl context? Actually every setting can be changed
5376      * on an existing gl context, so there's no real need for recreation.
5377      *
5378      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
5379      *
5380      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
5381      */
5382     TRACE("New params:\n");
5383     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
5384     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
5385     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
5386     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
5387     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
5388     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
5389     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
5390     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
5391     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
5392     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
5393     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
5394     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
5395     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
5396
5397     /* No special treatment of these parameters. Just store them */
5398     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
5399     swapchain->presentParms.Flags = pPresentationParameters->Flags;
5400     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
5401     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
5402
5403     /* What to do about these? */
5404     if(pPresentationParameters->BackBufferCount != 0 &&
5405         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
5406         ERR("Cannot change the back buffer count yet\n");
5407     }
5408     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
5409         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
5410         ERR("Cannot change the back buffer format yet\n");
5411     }
5412     if(pPresentationParameters->hDeviceWindow != NULL &&
5413         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
5414         ERR("Cannot change the device window yet\n");
5415     }
5416     if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
5417         ERR("What do do about a changed auto depth stencil parameter?\n");
5418     }
5419
5420     if(pPresentationParameters->Windowed) {
5421         mode.Width = swapchain->orig_width;
5422         mode.Height = swapchain->orig_height;
5423         mode.RefreshRate = 0;
5424         mode.Format = swapchain->presentParms.BackBufferFormat;
5425     } else {
5426         mode.Width = pPresentationParameters->BackBufferWidth;
5427         mode.Height = pPresentationParameters->BackBufferHeight;
5428         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
5429         mode.Format = swapchain->presentParms.BackBufferFormat;
5430     }
5431
5432     /* Should Width == 800 && Height == 0 set 800x600? */
5433     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
5434        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
5435         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
5436     {
5437         WINED3DVIEWPORT vp;
5438         int i;
5439
5440         vp.X = 0;
5441         vp.Y = 0;
5442         vp.Width = pPresentationParameters->BackBufferWidth;
5443         vp.Height = pPresentationParameters->BackBufferHeight;
5444         vp.MinZ = 0;
5445         vp.MaxZ = 1;
5446
5447         if(!pPresentationParameters->Windowed) {
5448             DisplayModeChanged = TRUE;
5449         }
5450         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
5451         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
5452
5453         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
5454         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
5455             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
5456         }
5457
5458         /* Now set the new viewport */
5459         IWineD3DDevice_SetViewport(iface, &vp);
5460     }
5461
5462     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
5463        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
5464         DisplayModeChanged) {
5465
5466         /* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */
5467         if(!pPresentationParameters->Windowed) {
5468             IWineD3DDevice_SetFullscreen(iface, TRUE);
5469         }
5470
5471         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
5472
5473         /* Switching out of fullscreen mode? First set the original res, then change the window */
5474         if(pPresentationParameters->Windowed) {
5475             IWineD3DDevice_SetFullscreen(iface, FALSE);
5476         }
5477         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
5478     }
5479
5480     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
5481     return WINED3D_OK;
5482 }
5483
5484 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5485     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5486     /** FIXME: always true at the moment **/
5487     if(!bEnableDialogs) {
5488         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5489     }
5490     return WINED3D_OK;
5491 }
5492
5493
5494 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
5495     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5496     TRACE("(%p) : pParameters %p\n", This, pParameters);
5497
5498     *pParameters = This->createParms;
5499     return WINED3D_OK;
5500 }
5501
5502 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
5503     IWineD3DSwapChain *swapchain;
5504     HRESULT hrc = WINED3D_OK;
5505
5506     TRACE("Relaying  to swapchain\n");
5507
5508     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5509         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
5510         IWineD3DSwapChain_Release(swapchain);
5511     }
5512     return;
5513 }
5514
5515 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
5516     IWineD3DSwapChain *swapchain;
5517     HRESULT hrc = WINED3D_OK;
5518
5519     TRACE("Relaying  to swapchain\n");
5520
5521     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5522         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5523         IWineD3DSwapChain_Release(swapchain);
5524     }
5525     return;
5526 }
5527
5528
5529 /** ********************************************************
5530 *   Notification functions
5531 ** ********************************************************/
5532 /** This function must be called in the release of a resource when ref == 0,
5533 * the contents of resource must still be correct,
5534 * any handels to other resource held by the caller must be closed
5535 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5536  *****************************************************/
5537 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5538     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5539     ResourceList* resourceList;
5540
5541     TRACE("(%p) : resource %p\n", This, resource);
5542 #if 0
5543     EnterCriticalSection(&resourceStoreCriticalSection);
5544 #endif
5545     /* add a new texture to the frot of the linked list */
5546     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5547     resourceList->resource = resource;
5548
5549     /* Get the old head */
5550     resourceList->next = This->resources;
5551
5552     This->resources = resourceList;
5553     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5554
5555 #if 0
5556     LeaveCriticalSection(&resourceStoreCriticalSection);
5557 #endif
5558     return;
5559 }
5560
5561 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5562     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5563     ResourceList* resourceList = NULL;
5564     ResourceList* previousResourceList = NULL;
5565     
5566     TRACE("(%p) : resource %p\n", This, resource);
5567
5568 #if 0
5569     EnterCriticalSection(&resourceStoreCriticalSection);
5570 #endif
5571     resourceList = This->resources;
5572
5573     while (resourceList != NULL) {
5574         if(resourceList->resource == resource) break;
5575         previousResourceList = resourceList;
5576         resourceList = resourceList->next;
5577     }
5578
5579     if (resourceList == NULL) {
5580         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5581 #if 0
5582         LeaveCriticalSection(&resourceStoreCriticalSection);
5583 #endif
5584         return;
5585     } else {
5586             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5587     }
5588     /* make sure we don't leave a hole in the list */
5589     if (previousResourceList != NULL) {
5590         previousResourceList->next = resourceList->next;
5591     } else {
5592         This->resources = resourceList->next;
5593     }
5594
5595 #if 0
5596     LeaveCriticalSection(&resourceStoreCriticalSection);
5597 #endif
5598     return;
5599 }
5600
5601
5602 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5603     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5604     int counter;
5605
5606     TRACE("(%p) : resource %p\n", This, resource);
5607     switch(IWineD3DResource_GetType(resource)){
5608         case WINED3DRTYPE_SURFACE:
5609         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
5610         break;
5611         case WINED3DRTYPE_TEXTURE:
5612         case WINED3DRTYPE_CUBETEXTURE:
5613         case WINED3DRTYPE_VOLUMETEXTURE:
5614                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
5615                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5616                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5617                         This->stateBlock->textures[counter] = NULL;
5618                     }
5619                     if (This->updateStateBlock != This->stateBlock ){
5620                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5621                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5622                             This->updateStateBlock->textures[counter] = NULL;
5623                         }
5624                     }
5625                 }
5626         break;
5627         case WINED3DRTYPE_VOLUME:
5628         /* TODO: nothing really? */
5629         break;
5630         case WINED3DRTYPE_VERTEXBUFFER:
5631         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5632         {
5633             int streamNumber;
5634             TRACE("Cleaning up stream pointers\n");
5635
5636             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5637                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5638                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5639                 */
5640                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5641                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5642                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5643                         This->updateStateBlock->streamSource[streamNumber] = 0;
5644                         /* Set changed flag? */
5645                     }
5646                 }
5647                 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) */
5648                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5649                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5650                         This->stateBlock->streamSource[streamNumber] = 0;
5651                     }
5652                 }
5653 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5654                  else { /* This shouldn't happen */
5655                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5656                 }
5657 #endif
5658
5659             }
5660         }
5661         break;
5662         case WINED3DRTYPE_INDEXBUFFER:
5663         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5664         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5665             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5666                 This->updateStateBlock->pIndexData =  NULL;
5667             }
5668         }
5669         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5670             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5671                 This->stateBlock->pIndexData =  NULL;
5672             }
5673         }
5674
5675         break;
5676         default:
5677         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
5678         break;
5679     }
5680
5681
5682     /* Remove the resoruce from the resourceStore */
5683     IWineD3DDeviceImpl_RemoveResource(iface, resource);
5684
5685     TRACE("Resource released\n");
5686
5687 }
5688
5689 /**********************************************************
5690  * IWineD3DDevice VTbl follows
5691  **********************************************************/
5692
5693 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5694 {
5695     /*** IUnknown methods ***/
5696     IWineD3DDeviceImpl_QueryInterface,
5697     IWineD3DDeviceImpl_AddRef,
5698     IWineD3DDeviceImpl_Release,
5699     /*** IWineD3DDevice methods ***/
5700     IWineD3DDeviceImpl_GetParent,
5701     /*** Creation methods**/
5702     IWineD3DDeviceImpl_CreateVertexBuffer,
5703     IWineD3DDeviceImpl_CreateIndexBuffer,
5704     IWineD3DDeviceImpl_CreateStateBlock,
5705     IWineD3DDeviceImpl_CreateSurface,
5706     IWineD3DDeviceImpl_CreateTexture,
5707     IWineD3DDeviceImpl_CreateVolumeTexture,
5708     IWineD3DDeviceImpl_CreateVolume,
5709     IWineD3DDeviceImpl_CreateCubeTexture,
5710     IWineD3DDeviceImpl_CreateQuery,
5711     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5712     IWineD3DDeviceImpl_CreateVertexDeclaration,
5713     IWineD3DDeviceImpl_CreateVertexShader,
5714     IWineD3DDeviceImpl_CreatePixelShader,
5715     IWineD3DDeviceImpl_CreatePalette,
5716     /*** Odd functions **/
5717     IWineD3DDeviceImpl_Init3D,
5718     IWineD3DDeviceImpl_Uninit3D,
5719     IWineD3DDeviceImpl_SetFullscreen,
5720     IWineD3DDeviceImpl_EvictManagedResources,
5721     IWineD3DDeviceImpl_GetAvailableTextureMem,
5722     IWineD3DDeviceImpl_GetBackBuffer,
5723     IWineD3DDeviceImpl_GetCreationParameters,
5724     IWineD3DDeviceImpl_GetDeviceCaps,
5725     IWineD3DDeviceImpl_GetDirect3D,
5726     IWineD3DDeviceImpl_GetDisplayMode,
5727     IWineD3DDeviceImpl_SetDisplayMode,
5728     IWineD3DDeviceImpl_GetHWND,
5729     IWineD3DDeviceImpl_SetHWND,
5730     IWineD3DDeviceImpl_GetNumberOfSwapChains,
5731     IWineD3DDeviceImpl_GetRasterStatus,
5732     IWineD3DDeviceImpl_GetSwapChain,
5733     IWineD3DDeviceImpl_Reset,
5734     IWineD3DDeviceImpl_SetDialogBoxMode,
5735     IWineD3DDeviceImpl_SetCursorProperties,
5736     IWineD3DDeviceImpl_SetCursorPosition,
5737     IWineD3DDeviceImpl_ShowCursor,
5738     IWineD3DDeviceImpl_TestCooperativeLevel,
5739     /*** Getters and setters **/
5740     IWineD3DDeviceImpl_SetClipPlane,
5741     IWineD3DDeviceImpl_GetClipPlane,
5742     IWineD3DDeviceImpl_SetClipStatus,
5743     IWineD3DDeviceImpl_GetClipStatus,
5744     IWineD3DDeviceImpl_SetCurrentTexturePalette,
5745     IWineD3DDeviceImpl_GetCurrentTexturePalette,
5746     IWineD3DDeviceImpl_SetDepthStencilSurface,
5747     IWineD3DDeviceImpl_GetDepthStencilSurface,
5748     IWineD3DDeviceImpl_SetFVF,
5749     IWineD3DDeviceImpl_GetFVF,
5750     IWineD3DDeviceImpl_SetGammaRamp,
5751     IWineD3DDeviceImpl_GetGammaRamp,
5752     IWineD3DDeviceImpl_SetIndices,
5753     IWineD3DDeviceImpl_GetIndices,
5754     IWineD3DDeviceImpl_SetBasevertexIndex,
5755     IWineD3DDeviceImpl_SetLight,
5756     IWineD3DDeviceImpl_GetLight,
5757     IWineD3DDeviceImpl_SetLightEnable,
5758     IWineD3DDeviceImpl_GetLightEnable,
5759     IWineD3DDeviceImpl_SetMaterial,
5760     IWineD3DDeviceImpl_GetMaterial,
5761     IWineD3DDeviceImpl_SetNPatchMode,
5762     IWineD3DDeviceImpl_GetNPatchMode,
5763     IWineD3DDeviceImpl_SetPaletteEntries,
5764     IWineD3DDeviceImpl_GetPaletteEntries,
5765     IWineD3DDeviceImpl_SetPixelShader,
5766     IWineD3DDeviceImpl_GetPixelShader,
5767     IWineD3DDeviceImpl_SetPixelShaderConstantB,
5768     IWineD3DDeviceImpl_GetPixelShaderConstantB,
5769     IWineD3DDeviceImpl_SetPixelShaderConstantI,
5770     IWineD3DDeviceImpl_GetPixelShaderConstantI,
5771     IWineD3DDeviceImpl_SetPixelShaderConstantF,
5772     IWineD3DDeviceImpl_GetPixelShaderConstantF,
5773     IWineD3DDeviceImpl_SetRenderState,
5774     IWineD3DDeviceImpl_GetRenderState,
5775     IWineD3DDeviceImpl_SetRenderTarget,
5776     IWineD3DDeviceImpl_GetRenderTarget,
5777     IWineD3DDeviceImpl_SetFrontBackBuffers,
5778     IWineD3DDeviceImpl_SetSamplerState,
5779     IWineD3DDeviceImpl_GetSamplerState,
5780     IWineD3DDeviceImpl_SetScissorRect,
5781     IWineD3DDeviceImpl_GetScissorRect,
5782     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5783     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5784     IWineD3DDeviceImpl_SetStreamSource,
5785     IWineD3DDeviceImpl_GetStreamSource,
5786     IWineD3DDeviceImpl_SetStreamSourceFreq,
5787     IWineD3DDeviceImpl_GetStreamSourceFreq,
5788     IWineD3DDeviceImpl_SetTexture,
5789     IWineD3DDeviceImpl_GetTexture,
5790     IWineD3DDeviceImpl_SetTextureStageState,
5791     IWineD3DDeviceImpl_GetTextureStageState,
5792     IWineD3DDeviceImpl_SetTransform,
5793     IWineD3DDeviceImpl_GetTransform,
5794     IWineD3DDeviceImpl_SetVertexDeclaration,
5795     IWineD3DDeviceImpl_GetVertexDeclaration,
5796     IWineD3DDeviceImpl_SetVertexShader,
5797     IWineD3DDeviceImpl_GetVertexShader,
5798     IWineD3DDeviceImpl_SetVertexShaderConstantB,
5799     IWineD3DDeviceImpl_GetVertexShaderConstantB,
5800     IWineD3DDeviceImpl_SetVertexShaderConstantI,
5801     IWineD3DDeviceImpl_GetVertexShaderConstantI,
5802     IWineD3DDeviceImpl_SetVertexShaderConstantF,
5803     IWineD3DDeviceImpl_GetVertexShaderConstantF,
5804     IWineD3DDeviceImpl_SetViewport,
5805     IWineD3DDeviceImpl_GetViewport,
5806     IWineD3DDeviceImpl_MultiplyTransform,
5807     IWineD3DDeviceImpl_ValidateDevice,
5808     IWineD3DDeviceImpl_ProcessVertices,
5809     /*** State block ***/
5810     IWineD3DDeviceImpl_BeginStateBlock,
5811     IWineD3DDeviceImpl_EndStateBlock,
5812     /*** Scene management ***/
5813     IWineD3DDeviceImpl_BeginScene,
5814     IWineD3DDeviceImpl_EndScene,
5815     IWineD3DDeviceImpl_Present,
5816     IWineD3DDeviceImpl_Clear,
5817     /*** Drawing ***/
5818     IWineD3DDeviceImpl_DrawPrimitive,
5819     IWineD3DDeviceImpl_DrawIndexedPrimitive,
5820     IWineD3DDeviceImpl_DrawPrimitiveUP,
5821     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5822     IWineD3DDeviceImpl_DrawPrimitiveStrided,
5823     IWineD3DDeviceImpl_DrawRectPatch,
5824     IWineD3DDeviceImpl_DrawTriPatch,
5825     IWineD3DDeviceImpl_DeletePatch,
5826     IWineD3DDeviceImpl_ColorFill,
5827     IWineD3DDeviceImpl_UpdateTexture,
5828     IWineD3DDeviceImpl_UpdateSurface,
5829     IWineD3DDeviceImpl_GetFrontBufferData,
5830     /*** object tracking ***/
5831     IWineD3DDeviceImpl_ResourceReleased
5832 };
5833
5834
5835 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5836     WINED3DRS_ALPHABLENDENABLE   ,
5837     WINED3DRS_ALPHAFUNC          ,
5838     WINED3DRS_ALPHAREF           ,
5839     WINED3DRS_ALPHATESTENABLE    ,
5840     WINED3DRS_BLENDOP            ,
5841     WINED3DRS_COLORWRITEENABLE   ,
5842     WINED3DRS_DESTBLEND          ,
5843     WINED3DRS_DITHERENABLE       ,
5844     WINED3DRS_FILLMODE           ,
5845     WINED3DRS_FOGDENSITY         ,
5846     WINED3DRS_FOGEND             ,
5847     WINED3DRS_FOGSTART           ,
5848     WINED3DRS_LASTPIXEL          ,
5849     WINED3DRS_SHADEMODE          ,
5850     WINED3DRS_SRCBLEND           ,
5851     WINED3DRS_STENCILENABLE      ,
5852     WINED3DRS_STENCILFAIL        ,
5853     WINED3DRS_STENCILFUNC        ,
5854     WINED3DRS_STENCILMASK        ,
5855     WINED3DRS_STENCILPASS        ,
5856     WINED3DRS_STENCILREF         ,
5857     WINED3DRS_STENCILWRITEMASK   ,
5858     WINED3DRS_STENCILZFAIL       ,
5859     WINED3DRS_TEXTUREFACTOR      ,
5860     WINED3DRS_WRAP0              ,
5861     WINED3DRS_WRAP1              ,
5862     WINED3DRS_WRAP2              ,
5863     WINED3DRS_WRAP3              ,
5864     WINED3DRS_WRAP4              ,
5865     WINED3DRS_WRAP5              ,
5866     WINED3DRS_WRAP6              ,
5867     WINED3DRS_WRAP7              ,
5868     WINED3DRS_ZENABLE            ,
5869     WINED3DRS_ZFUNC              ,
5870     WINED3DRS_ZWRITEENABLE
5871 };
5872
5873 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5874     WINED3DTSS_ADDRESSW              ,
5875     WINED3DTSS_ALPHAARG0             ,
5876     WINED3DTSS_ALPHAARG1             ,
5877     WINED3DTSS_ALPHAARG2             ,
5878     WINED3DTSS_ALPHAOP               ,
5879     WINED3DTSS_BUMPENVLOFFSET        ,
5880     WINED3DTSS_BUMPENVLSCALE         ,
5881     WINED3DTSS_BUMPENVMAT00          ,
5882     WINED3DTSS_BUMPENVMAT01          ,
5883     WINED3DTSS_BUMPENVMAT10          ,
5884     WINED3DTSS_BUMPENVMAT11          ,
5885     WINED3DTSS_COLORARG0             ,
5886     WINED3DTSS_COLORARG1             ,
5887     WINED3DTSS_COLORARG2             ,
5888     WINED3DTSS_COLOROP               ,
5889     WINED3DTSS_RESULTARG             ,
5890     WINED3DTSS_TEXCOORDINDEX         ,
5891     WINED3DTSS_TEXTURETRANSFORMFLAGS
5892 };
5893
5894 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5895     WINED3DSAMP_ADDRESSU         ,
5896     WINED3DSAMP_ADDRESSV         ,
5897     WINED3DSAMP_ADDRESSW         ,
5898     WINED3DSAMP_BORDERCOLOR      ,
5899     WINED3DSAMP_MAGFILTER        ,
5900     WINED3DSAMP_MINFILTER        ,
5901     WINED3DSAMP_MIPFILTER        ,
5902     WINED3DSAMP_MIPMAPLODBIAS    ,
5903     WINED3DSAMP_MAXMIPLEVEL      ,
5904     WINED3DSAMP_MAXANISOTROPY    ,
5905     WINED3DSAMP_SRGBTEXTURE      ,
5906     WINED3DSAMP_ELEMENTINDEX
5907 };
5908
5909 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5910     WINED3DRS_AMBIENT                       ,
5911     WINED3DRS_AMBIENTMATERIALSOURCE         ,
5912     WINED3DRS_CLIPPING                      ,
5913     WINED3DRS_CLIPPLANEENABLE               ,
5914     WINED3DRS_COLORVERTEX                   ,
5915     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
5916     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
5917     WINED3DRS_FOGDENSITY                    ,
5918     WINED3DRS_FOGEND                        ,
5919     WINED3DRS_FOGSTART                      ,
5920     WINED3DRS_FOGTABLEMODE                  ,
5921     WINED3DRS_FOGVERTEXMODE                 ,
5922     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
5923     WINED3DRS_LIGHTING                      ,
5924     WINED3DRS_LOCALVIEWER                   ,
5925     WINED3DRS_MULTISAMPLEANTIALIAS          ,
5926     WINED3DRS_MULTISAMPLEMASK               ,
5927     WINED3DRS_NORMALIZENORMALS              ,
5928     WINED3DRS_PATCHEDGESTYLE                ,
5929     WINED3DRS_POINTSCALE_A                  ,
5930     WINED3DRS_POINTSCALE_B                  ,
5931     WINED3DRS_POINTSCALE_C                  ,
5932     WINED3DRS_POINTSCALEENABLE              ,
5933     WINED3DRS_POINTSIZE                     ,
5934     WINED3DRS_POINTSIZE_MAX                 ,
5935     WINED3DRS_POINTSIZE_MIN                 ,
5936     WINED3DRS_POINTSPRITEENABLE             ,
5937     WINED3DRS_RANGEFOGENABLE                ,
5938     WINED3DRS_SPECULARMATERIALSOURCE        ,
5939     WINED3DRS_TWEENFACTOR                   ,
5940     WINED3DRS_VERTEXBLEND
5941 };
5942
5943 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5944     WINED3DTSS_TEXCOORDINDEX         ,
5945     WINED3DTSS_TEXTURETRANSFORMFLAGS
5946 };
5947
5948 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5949     WINED3DSAMP_DMAPOFFSET
5950 };
5951
5952 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
5953     DWORD rep = StateTable[state].representative;
5954     DWORD idx;
5955     BYTE shift;
5956     UINT i;
5957     WineD3DContext *context;
5958
5959     if(!rep) return;
5960     for(i = 0; i < This->numContexts; i++) {
5961         context = This->contexts[i];
5962         if(isStateDirty(context, rep)) continue;
5963
5964         context->dirtyArray[context->numDirtyEntries++] = rep;
5965         idx = rep >> 5;
5966         shift = rep & 0x1f;
5967         context->isStateDirty[idx] |= (1 << shift);
5968     }
5969 }