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