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