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