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