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