wined3d: Use CopyRect / EqualRect.
[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(EqualRect(&This->updateStateBlock->scissorRect, pRect)) {
2817         TRACE("App is setting the old scissor rectangle over, nothing to do\n");
2818         return WINED3D_OK;
2819     }
2820     CopyRect(&This->updateStateBlock->scissorRect, pRect);
2821
2822     if(This->isRecordingState) {
2823         TRACE("Recording... not performing anything\n");
2824         return WINED3D_OK;
2825     }
2826
2827     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
2828
2829     return WINED3D_OK;
2830 }
2831
2832 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
2833     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2834
2835     memcpy(pRect, &This->updateStateBlock->scissorRect, sizeof(pRect));
2836     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2837     return WINED3D_OK;
2838 }
2839
2840 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
2841     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2842     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
2843
2844     TRACE("(%p) : pDecl=%p\n", This, pDecl);
2845
2846     This->updateStateBlock->vertexDecl = pDecl;
2847     This->updateStateBlock->changed.vertexDecl = TRUE;
2848     This->updateStateBlock->set.vertexDecl = TRUE;
2849
2850     if (This->isRecordingState) {
2851         TRACE("Recording... not performing anything\n");
2852         return WINED3D_OK;
2853     } else if(pDecl == oldDecl) {
2854         /* Checked after the assignment to allow proper stateblock recording */
2855         TRACE("Application is setting the old declaration over, nothing to do\n");
2856         return WINED3D_OK;
2857     }
2858
2859     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
2860     return WINED3D_OK;
2861 }
2862
2863 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
2864     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2865
2866     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
2867
2868     *ppDecl = This->stateBlock->vertexDecl;
2869     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
2870     return WINED3D_OK;
2871 }
2872
2873 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
2874     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
2875     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
2876
2877     This->updateStateBlock->vertexShader         = pShader;
2878     This->updateStateBlock->changed.vertexShader = TRUE;
2879     This->updateStateBlock->set.vertexShader     = TRUE;
2880
2881     if (This->isRecordingState) {
2882         TRACE("Recording... not performing anything\n");
2883         return WINED3D_OK;
2884     } else if(oldShader == pShader) {
2885         /* Checked here to allow proper stateblock recording */
2886         TRACE("App is setting the old shader over, nothing to do\n");
2887         return WINED3D_OK;
2888     }
2889
2890     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
2891
2892     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
2893
2894     return WINED3D_OK;
2895 }
2896
2897 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
2898     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2899
2900     if (NULL == ppShader) {
2901         return WINED3DERR_INVALIDCALL;
2902     }
2903     *ppShader = This->stateBlock->vertexShader;
2904     if( NULL != *ppShader)
2905         IWineD3DVertexShader_AddRef(*ppShader);
2906
2907     TRACE("(%p) : returning %p\n", This, *ppShader);
2908     return WINED3D_OK;
2909 }
2910
2911 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
2912     IWineD3DDevice *iface,
2913     UINT start,
2914     CONST BOOL *srcData,
2915     UINT count) {
2916
2917     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2918     int i, cnt = min(count, MAX_CONST_B - start);
2919
2920     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2921             iface, srcData, start, count);
2922
2923     if (srcData == NULL || cnt < 0)
2924         return WINED3DERR_INVALIDCALL;
2925
2926     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
2927     for (i = 0; i < cnt; i++)
2928         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
2929
2930     for (i = start; i < cnt + start; ++i) {
2931         This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
2932         This->updateStateBlock->set.vertexShaderConstantsB[i]     = TRUE;
2933     }
2934
2935     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
2936
2937     return WINED3D_OK;
2938 }
2939
2940 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
2941     IWineD3DDevice *iface,
2942     UINT start,
2943     BOOL *dstData,
2944     UINT count) {
2945
2946     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2947     int cnt = min(count, MAX_CONST_B - start);
2948
2949     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2950             iface, dstData, start, count);
2951
2952     if (dstData == NULL || cnt < 0)
2953         return WINED3DERR_INVALIDCALL;
2954
2955     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
2956     return WINED3D_OK;
2957 }
2958
2959 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
2960     IWineD3DDevice *iface,
2961     UINT start,
2962     CONST int *srcData,
2963     UINT count) {
2964
2965     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2966     int i, cnt = min(count, MAX_CONST_I - start);
2967
2968     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2969             iface, srcData, start, count);
2970
2971     if (srcData == NULL || cnt < 0)
2972         return WINED3DERR_INVALIDCALL;
2973
2974     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
2975     for (i = 0; i < cnt; i++)
2976         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
2977            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
2978
2979     for (i = start; i < cnt + start; ++i) {
2980         This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
2981         This->updateStateBlock->set.vertexShaderConstantsI[i]     = TRUE;
2982     }
2983
2984     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
2985
2986     return WINED3D_OK;
2987 }
2988
2989 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
2990     IWineD3DDevice *iface,
2991     UINT start,
2992     int *dstData,
2993     UINT count) {
2994
2995     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2996     int cnt = min(count, MAX_CONST_I - start);
2997
2998     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2999             iface, dstData, start, count);
3000
3001     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
3002         return WINED3DERR_INVALIDCALL;
3003
3004     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3005     return WINED3D_OK;
3006 }
3007
3008 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
3009     IWineD3DDevice *iface,
3010     UINT start,
3011     CONST float *srcData,
3012     UINT count) {
3013
3014     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3015     int i;
3016
3017     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3018             iface, srcData, start, count);
3019
3020     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3021     if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
3022         return WINED3DERR_INVALIDCALL;
3023
3024     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3025     if(TRACE_ON(d3d)) {
3026         for (i = 0; i < count; i++)
3027             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3028                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3029     }
3030
3031     for (i = start; i < count + start; ++i) {
3032         if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
3033             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
3034             ptr->idx = i;
3035             list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
3036             This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
3037         }
3038         This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
3039     }
3040
3041     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3042
3043     return WINED3D_OK;
3044 }
3045
3046 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3047     IWineD3DDevice *iface,
3048     UINT start,
3049     float *dstData,
3050     UINT count) {
3051
3052     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3053     int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3054
3055     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3056             iface, dstData, start, count);
3057
3058     if (dstData == NULL || cnt < 0)
3059         return WINED3DERR_INVALIDCALL;
3060
3061     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3062     return WINED3D_OK;
3063 }
3064
3065 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3066     DWORD i;
3067     for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
3068         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3069     }
3070 }
3071
3072 static void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3073     DWORD i, tex;
3074     /* This code can assume that GL_NV_register_combiners are supported, otherwise
3075      * it is never called.
3076      *
3077      * Rules are:
3078      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3079      * that would be really messy and require shader recompilation
3080      * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3081      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3082      * -> Whith a 1:1 mapping oneToOneTexUnitMap is set to avoid checking MAX_SAMPLERS array
3083      * entries to make pixel shaders cheaper. MAX_SAMPLERS will be 128 in dx10
3084      */
3085     if(This->stateBlock->pixelShader || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) {
3086         if(This->oneToOneTexUnitMap) {
3087             TRACE("Not touching 1:1 map\n");
3088             return;
3089         }
3090         TRACE("Restoring 1:1 texture unit mapping\n");
3091         /* Restore a 1:1 mapping */
3092         for(i = 0; i < MAX_SAMPLERS; i++) {
3093             if(This->texUnitMap[i] != i) {
3094                 This->texUnitMap[i] = i;
3095                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3096                 markTextureStagesDirty(This, i);
3097             }
3098         }
3099         This->oneToOneTexUnitMap = TRUE;
3100         return;
3101     } else {
3102         /* No pixel shader, and we do not have enough texture units available. Try to skip NULL textures
3103          * First, see if we can succeed at all
3104          */
3105         tex = 0;
3106         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3107             if(This->stateBlock->textures[i] == NULL) tex++;
3108         }
3109
3110         if(GL_LIMITS(textures) + tex < This->stateBlock->lowest_disabled_stage) {
3111             FIXME("Too many bound textures to support the combiner settings\n");
3112             return;
3113         }
3114
3115         /* Now work out the mapping */
3116         tex = 0;
3117         This->oneToOneTexUnitMap = FALSE;
3118         WARN("Non 1:1 mapping UNTESTED!\n");
3119         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3120             /* Skip NULL textures */
3121             if (!This->stateBlock->textures[i]) {
3122                 /* Map to -1, so the check below doesn't fail if a non-NULL
3123                  * texture is set on this stage */
3124                 TRACE("Mapping texture stage %d to -1\n", i);
3125                 This->texUnitMap[i] = -1;
3126
3127                 continue;
3128             }
3129
3130             TRACE("Mapping texture stage %d to unit %d\n", i, tex);
3131             if(This->texUnitMap[i] != tex) {
3132                 This->texUnitMap[i] = tex;
3133                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3134                 markTextureStagesDirty(This, i);
3135             }
3136
3137             ++tex;
3138         }
3139     }
3140 }
3141
3142 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3143     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3144     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3145     This->updateStateBlock->pixelShader         = pShader;
3146     This->updateStateBlock->changed.pixelShader = TRUE;
3147     This->updateStateBlock->set.pixelShader     = TRUE;
3148
3149     /* Handle recording of state blocks */
3150     if (This->isRecordingState) {
3151         TRACE("Recording... not performing anything\n");
3152     }
3153
3154     if (This->isRecordingState) {
3155         TRACE("Recording... not performing anything\n");
3156         return WINED3D_OK;
3157     }
3158
3159     if(pShader == oldShader) {
3160         TRACE("App is setting the old pixel shader over, nothing to do\n");
3161         return WINED3D_OK;
3162     }
3163
3164     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3165     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3166
3167     /* Rebuild the texture unit mapping if nvrc's are supported */
3168     if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3169         IWineD3DDeviceImpl_FindTexUnitMap(This);
3170     }
3171
3172     return WINED3D_OK;
3173 }
3174
3175 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3176     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3177
3178     if (NULL == ppShader) {
3179         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3180         return WINED3DERR_INVALIDCALL;
3181     }
3182
3183     *ppShader =  This->stateBlock->pixelShader;
3184     if (NULL != *ppShader) {
3185         IWineD3DPixelShader_AddRef(*ppShader);
3186     }
3187     TRACE("(%p) : returning %p\n", This, *ppShader);
3188     return WINED3D_OK;
3189 }
3190
3191 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3192     IWineD3DDevice *iface,
3193     UINT start,
3194     CONST BOOL *srcData,
3195     UINT count) {
3196
3197     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3198     int i, cnt = min(count, MAX_CONST_B - start);
3199
3200     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3201             iface, srcData, start, count);
3202
3203     if (srcData == NULL || cnt < 0)
3204         return WINED3DERR_INVALIDCALL;
3205
3206     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3207     for (i = 0; i < cnt; i++)
3208         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3209
3210     for (i = start; i < cnt + start; ++i) {
3211         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3212         This->updateStateBlock->set.pixelShaderConstantsB[i]     = TRUE;
3213     }
3214
3215     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3216
3217     return WINED3D_OK;
3218 }
3219
3220 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3221     IWineD3DDevice *iface,
3222     UINT start,
3223     BOOL *dstData,
3224     UINT count) {
3225
3226     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3227     int cnt = min(count, MAX_CONST_B - start);
3228
3229     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3230             iface, dstData, start, count);
3231
3232     if (dstData == NULL || cnt < 0)
3233         return WINED3DERR_INVALIDCALL;
3234
3235     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3236     return WINED3D_OK;
3237 }
3238
3239 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3240     IWineD3DDevice *iface,
3241     UINT start,
3242     CONST int *srcData,
3243     UINT count) {
3244
3245     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3246     int i, cnt = min(count, MAX_CONST_I - start);
3247
3248     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3249             iface, srcData, start, count);
3250
3251     if (srcData == NULL || cnt < 0)
3252         return WINED3DERR_INVALIDCALL;
3253
3254     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3255     for (i = 0; i < cnt; i++)
3256         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3257            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3258
3259     for (i = start; i < cnt + start; ++i) {
3260         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3261         This->updateStateBlock->set.pixelShaderConstantsI[i]     = TRUE;
3262     }
3263
3264     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3265
3266     return WINED3D_OK;
3267 }
3268
3269 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3270     IWineD3DDevice *iface,
3271     UINT start,
3272     int *dstData,
3273     UINT count) {
3274
3275     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3276     int cnt = min(count, MAX_CONST_I - start);
3277
3278     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3279             iface, dstData, start, count);
3280
3281     if (dstData == NULL || cnt < 0)
3282         return WINED3DERR_INVALIDCALL;
3283
3284     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3285     return WINED3D_OK;
3286 }
3287
3288 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3289     IWineD3DDevice *iface,
3290     UINT start,
3291     CONST float *srcData,
3292     UINT count) {
3293
3294     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3295     int i;
3296
3297     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3298             iface, srcData, start, count);
3299
3300     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3301     if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
3302         return WINED3DERR_INVALIDCALL;
3303
3304     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3305     if(TRACE_ON(d3d)) {
3306         for (i = 0; i < count; i++)
3307             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3308                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3309     }
3310
3311     for (i = start; i < count + start; ++i) {
3312         if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3313             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
3314             ptr->idx = i;
3315             list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3316             This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3317         }
3318         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3319     }
3320
3321     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3322
3323     return WINED3D_OK;
3324 }
3325
3326 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3327     IWineD3DDevice *iface,
3328     UINT start,
3329     float *dstData,
3330     UINT count) {
3331
3332     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3333     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3334
3335     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3336             iface, dstData, start, count);
3337
3338     if (dstData == NULL || cnt < 0)
3339         return WINED3DERR_INVALIDCALL;
3340
3341     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3342     return WINED3D_OK;
3343 }
3344
3345 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3346 static HRESULT
3347 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3348     char *dest_ptr, *dest_conv = NULL;
3349     unsigned int i;
3350     DWORD DestFVF = dest->fvf;
3351     WINED3DVIEWPORT vp;
3352     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3353     BOOL doClip;
3354     int numTextures;
3355
3356     if (SrcFVF & WINED3DFVF_NORMAL) {
3357         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3358     }
3359
3360     if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
3361         ERR("Source has no position mask\n");
3362         return WINED3DERR_INVALIDCALL;
3363     }
3364
3365     /* We might access VBOs from this code, so hold the lock */
3366     ENTER_GL();
3367
3368     if (dest->resource.allocatedMemory == NULL) {
3369         /* This may happen if we do direct locking into a vbo. Unlikely,
3370          * but theoretically possible(ddraw processvertices test)
3371          */
3372         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3373         if(!dest->resource.allocatedMemory) {
3374             LEAVE_GL();
3375             ERR("Out of memory\n");
3376             return E_OUTOFMEMORY;
3377         }
3378         if(dest->vbo) {
3379             void *src;
3380             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3381             checkGLcall("glBindBufferARB");
3382             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3383             if(src) {
3384                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3385             }
3386             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3387             checkGLcall("glUnmapBufferARB");
3388         }
3389     }
3390
3391     /* Get a pointer into the destination vbo(create one if none exists) and
3392      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3393      */
3394     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3395         CreateVBO(dest);
3396     }
3397
3398     if(dest->vbo) {
3399         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3400         dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
3401         if(!dest_conv) {
3402             ERR("glMapBuffer failed\n");
3403             /* Continue without storing converted vertices */
3404         }
3405     }
3406
3407     /* Should I clip?
3408      * a) WINED3DRS_CLIPPING is enabled
3409      * b) WINED3DVOP_CLIP is passed
3410      */
3411     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3412         static BOOL warned = FALSE;
3413         /*
3414          * The clipping code is not quite correct. Some things need
3415          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3416          * so disable clipping for now.
3417          * (The graphics in Half-Life are broken, and my processvertices
3418          *  test crashes with IDirect3DDevice3)
3419         doClip = TRUE;
3420          */
3421         doClip = FALSE;
3422         if(!warned) {
3423            warned = TRUE;
3424            FIXME("Clipping is broken and disabled for now\n");
3425         }
3426     } else doClip = FALSE;
3427     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3428     if(dest_conv) {
3429         dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3430     }
3431
3432     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3433                                  WINED3DTS_VIEW,
3434                                  &view_mat);
3435     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3436                                  WINED3DTS_PROJECTION,
3437                                  &proj_mat);
3438     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3439                                  WINED3DTS_WORLDMATRIX(0),
3440                                  &world_mat);
3441
3442     TRACE("View mat:\n");
3443     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);
3444     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);
3445     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);
3446     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);
3447
3448     TRACE("Proj mat:\n");
3449     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);
3450     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);
3451     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);
3452     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);
3453
3454     TRACE("World mat:\n");
3455     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);
3456     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);
3457     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);
3458     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);
3459
3460     /* Get the viewport */
3461     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3462     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3463           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3464
3465     multiply_matrix(&mat,&view_mat,&world_mat);
3466     multiply_matrix(&mat,&proj_mat,&mat);
3467
3468     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3469
3470     for (i = 0; i < dwCount; i+= 1) {
3471         unsigned int tex_index;
3472
3473         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3474              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3475             /* The position first */
3476             float *p =
3477               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
3478             float x, y, z, rhw;
3479             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3480
3481             /* Multiplication with world, view and projection matrix */
3482             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);
3483             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);
3484             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);
3485             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);
3486
3487             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3488
3489             /* WARNING: The following things are taken from d3d7 and were not yet checked
3490              * against d3d8 or d3d9!
3491              */
3492
3493             /* Clipping conditions: From
3494              * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
3495              *
3496              * A vertex is clipped if it does not match the following requirements
3497              * -rhw < x <= rhw
3498              * -rhw < y <= rhw
3499              *    0 < z <= rhw
3500              *    0 < rhw ( Not in d3d7, but tested in d3d7)
3501              *
3502              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3503              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3504              *
3505              */
3506
3507             if( !doClip ||
3508                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3509                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
3510                   ( rhw > eps ) ) ) {
3511
3512                 /* "Normal" viewport transformation (not clipped)
3513                  * 1) The values are divided by rhw
3514                  * 2) The y axis is negative, so multiply it with -1
3515                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3516                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3517                  * 4) Multiply x with Width/2 and add Width/2
3518                  * 5) The same for the height
3519                  * 6) Add the viewpoint X and Y to the 2D coordinates and
3520                  *    The minimum Z value to z
3521                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3522                  *
3523                  * Well, basically it's simply a linear transformation into viewport
3524                  * coordinates
3525                  */
3526
3527                 x /= rhw;
3528                 y /= rhw;
3529                 z /= rhw;
3530
3531                 y *= -1;
3532
3533                 x *= vp.Width / 2;
3534                 y *= vp.Height / 2;
3535                 z *= vp.MaxZ - vp.MinZ;
3536
3537                 x += vp.Width / 2 + vp.X;
3538                 y += vp.Height / 2 + vp.Y;
3539                 z += vp.MinZ;
3540
3541                 rhw = 1 / rhw;
3542             } else {
3543                 /* That vertex got clipped
3544                  * Contrary to OpenGL it is not dropped completely, it just
3545                  * undergoes a different calculation.
3546                  */
3547                 TRACE("Vertex got clipped\n");
3548                 x += rhw;
3549                 y += rhw;
3550
3551                 x  /= 2;
3552                 y  /= 2;
3553
3554                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3555                  * outside of the main vertex buffer memory. That needs some more
3556                  * investigation...
3557                  */
3558             }
3559
3560             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3561
3562
3563             ( (float *) dest_ptr)[0] = x;
3564             ( (float *) dest_ptr)[1] = y;
3565             ( (float *) dest_ptr)[2] = z;
3566             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3567
3568             dest_ptr += 3 * sizeof(float);
3569
3570             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3571                 dest_ptr += sizeof(float);
3572             }
3573
3574             if(dest_conv) {
3575                 float w = 1 / rhw;
3576                 ( (float *) dest_conv)[0] = x * w;
3577                 ( (float *) dest_conv)[1] = y * w;
3578                 ( (float *) dest_conv)[2] = z * w;
3579                 ( (float *) dest_conv)[3] = w;
3580
3581                 dest_conv += 3 * sizeof(float);
3582
3583                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3584                     dest_conv += sizeof(float);
3585                 }
3586             }
3587         }
3588         if (DestFVF & WINED3DFVF_PSIZE) {
3589             dest_ptr += sizeof(DWORD);
3590             if(dest_conv) dest_conv += sizeof(DWORD);
3591         }
3592         if (DestFVF & WINED3DFVF_NORMAL) {
3593             float *normal =
3594               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
3595             /* AFAIK this should go into the lighting information */
3596             FIXME("Didn't expect the destination to have a normal\n");
3597             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3598             if(dest_conv) {
3599                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
3600             }
3601         }
3602
3603         if (DestFVF & WINED3DFVF_DIFFUSE) {
3604             DWORD *color_d = 
3605               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
3606             if(!color_d) {
3607                 static BOOL warned = FALSE;
3608
3609                 if(!warned) {
3610                     ERR("No diffuse color in source, but destination has one\n");
3611                     warned = TRUE;
3612                 }
3613
3614                 *( (DWORD *) dest_ptr) = 0xffffffff;
3615                 dest_ptr += sizeof(DWORD);
3616
3617                 if(dest_conv) {
3618                     *( (DWORD *) dest_conv) = 0xffffffff;
3619                     dest_conv += sizeof(DWORD);
3620                 }
3621             }
3622             else {
3623                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3624                 if(dest_conv) {
3625                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
3626                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
3627                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
3628                     dest_conv += sizeof(DWORD);
3629                 }
3630             }
3631         }
3632
3633         if (DestFVF & WINED3DFVF_SPECULAR) { 
3634             /* What's the color value in the feedback buffer? */
3635             DWORD *color_s = 
3636               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
3637             if(!color_s) {
3638                 static BOOL warned = FALSE;
3639
3640                 if(!warned) {
3641                     ERR("No specular color in source, but destination has one\n");
3642                     warned = TRUE;
3643                 }
3644
3645                 *( (DWORD *) dest_ptr) = 0xFF000000;
3646                 dest_ptr += sizeof(DWORD);
3647
3648                 if(dest_conv) {
3649                     *( (DWORD *) dest_conv) = 0xFF000000;
3650                     dest_conv += sizeof(DWORD);
3651                 }
3652             }
3653             else {
3654                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3655                 if(dest_conv) {
3656                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
3657                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
3658                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
3659                     dest_conv += sizeof(DWORD);
3660                 }
3661             }
3662         }
3663
3664         for (tex_index = 0; tex_index < numTextures; tex_index++) {
3665             float *tex_coord =
3666               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
3667                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
3668             if(!tex_coord) {
3669                 ERR("No source texture, but destination requests one\n");
3670                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3671                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3672             }
3673             else {
3674                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3675                 if(dest_conv) {
3676                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3677                 }
3678             }
3679         }
3680     }
3681
3682     if(dest_conv) {
3683         GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3684         checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
3685     }
3686
3687     LEAVE_GL();
3688
3689     return WINED3D_OK;
3690 }
3691 #undef copy_and_next
3692
3693 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3694     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3695     IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
3696     WineDirect3DVertexStridedData strided;
3697     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
3698
3699     if (!SrcImpl) {
3700         WARN("NULL source vertex buffer\n");
3701         return WINED3DERR_INVALIDCALL;
3702     }
3703     /* We don't need the source vbo because this buffer is only used as
3704      * a source for ProcessVertices. Avoid wasting resources by converting the
3705      * buffer and loading the VBO
3706      */
3707     if(SrcImpl->vbo) {
3708         TRACE("Releasing the source vbo, it won't be needed\n");
3709
3710         if(!SrcImpl->resource.allocatedMemory) {
3711             /* Rescue the data from the buffer */
3712             void *src;
3713             SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
3714             if(!SrcImpl->resource.allocatedMemory) {
3715                 ERR("Out of memory\n");
3716                 return E_OUTOFMEMORY;
3717             }
3718
3719             ENTER_GL();
3720             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
3721             checkGLcall("glBindBufferARB");
3722
3723             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3724             if(src) {
3725                 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
3726             }
3727
3728             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3729             checkGLcall("glUnmapBufferARB");
3730         } else {
3731             ENTER_GL();
3732         }
3733
3734         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
3735         checkGLcall("glBindBufferARB");
3736         GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
3737         checkGLcall("glDeleteBuffersARB");
3738         LEAVE_GL();
3739
3740         SrcImpl->vbo = 0;
3741     }
3742
3743     memset(&strided, 0, sizeof(strided));
3744     primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0, 0);
3745
3746     return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
3747 }
3748
3749 /*****
3750  * Get / Set Texture Stage States
3751  * TODO: Verify against dx9 definitions
3752  *****/
3753 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3754     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3755     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
3756
3757     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3758
3759     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3760
3761     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3762     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
3763     This->updateStateBlock->textureState[Stage][Type]         = Value;
3764
3765     if (This->isRecordingState) {
3766         TRACE("Recording... not performing anything\n");
3767         return WINED3D_OK;
3768     }
3769
3770     /* Checked after the assignments to allow proper stateblock recording */
3771     if(oldValue == Value) {
3772         TRACE("App is setting the old value over, nothing to do\n");
3773         return WINED3D_OK;
3774     }
3775
3776     if(Stage > This->stateBlock->lowest_disabled_stage &&
3777        StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
3778         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
3779          * Changes in other states are important on disabled stages too
3780          */
3781         return WINED3D_OK;
3782     }
3783
3784     if(Type == WINED3DTSS_COLOROP) {
3785         int i;
3786
3787         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
3788             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
3789              * they have to be disabled
3790              *
3791              * The current stage is dirtified below.
3792              */
3793             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
3794                 TRACE("Additionally dirtifying stage %d\n", i);
3795                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3796             }
3797             This->stateBlock->lowest_disabled_stage = Stage;
3798             TRACE("New lowest disabled: %d\n", Stage);
3799         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
3800             /* Previously disabled stage enabled. Stages above it may need enabling
3801              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
3802              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
3803              *
3804              * Again stage Stage doesn't need to be dirtified here, it is handled below.
3805              */
3806
3807             for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
3808                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
3809                     break;
3810                 }
3811                 TRACE("Additionally dirtifying stage %d due to enable\n", i);
3812                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3813             }
3814             This->stateBlock->lowest_disabled_stage = i;
3815             TRACE("New lowest disabled: %d\n", i);
3816         }
3817         if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3818             /* TODO: Built a stage -> texture unit mapping for register combiners */
3819         }
3820     }
3821
3822     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
3823
3824     /* Rebuild the stage -> gl texture unit mapping if register combiners are supported
3825      * If there is a pixel shader there will be a 1:1 mapping, no need to touch it. SetPixelShader
3826      * will call FindTexUnitMap too.
3827      */
3828     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3829         IWineD3DDeviceImpl_FindTexUnitMap(This);
3830     }
3831     return WINED3D_OK;
3832 }
3833
3834 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3835     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3836     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3837     *pValue = This->updateStateBlock->textureState[Stage][Type];
3838     return WINED3D_OK;
3839 }
3840
3841 /*****
3842  * Get / Set Texture
3843  *****/
3844 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3845
3846     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3847     IWineD3DBaseTexture   *oldTexture;
3848
3849     oldTexture = This->updateStateBlock->textures[Stage];
3850     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
3851
3852 #if 0 /* TODO: check so vertex textures */
3853     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
3854         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
3855         return WINED3D_OK;
3856     }
3857 #endif
3858
3859     if(pTexture != NULL) {
3860         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
3861          */
3862         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
3863             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
3864             return WINED3DERR_INVALIDCALL;
3865         }
3866         This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
3867     }
3868
3869     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
3870     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
3871
3872     This->updateStateBlock->set.textures[Stage]     = TRUE;
3873     This->updateStateBlock->changed.textures[Stage] = TRUE;
3874     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
3875     This->updateStateBlock->textures[Stage]         = pTexture;
3876
3877     /* Handle recording of state blocks */
3878     if (This->isRecordingState) {
3879         TRACE("Recording... not performing anything\n");
3880         return WINED3D_OK;
3881     }
3882
3883     if(oldTexture == pTexture) {
3884         TRACE("App is setting the same texture again, nothing to do\n");
3885         return WINED3D_OK;
3886     }
3887
3888     /** NOTE: MSDN says that setTexture increases the reference count,
3889     * and the the application nust set the texture back to null (or have a leaky application),
3890     * This means we should pass the refcount up to the parent
3891      *******************************/
3892     if (NULL != This->updateStateBlock->textures[Stage]) {
3893         IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
3894         ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
3895
3896         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
3897         if(oldTexture == NULL && Stage < MAX_TEXTURES) {
3898             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
3899              * so the COLOROP and ALPHAOP have to be dirtified.
3900              */
3901             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
3902             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
3903         }
3904         if(bindCount == 1) {
3905             new->baseTexture.sampler = Stage;
3906         }
3907         /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
3908
3909     }
3910
3911     if (NULL != oldTexture) {
3912         IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
3913         LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
3914
3915         IWineD3DBaseTexture_Release(oldTexture);
3916         if(pTexture == NULL && Stage < MAX_TEXTURES) {
3917             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
3918             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
3919         }
3920
3921         if(bindCount && old->baseTexture.sampler == Stage) {
3922             int i;
3923             /* Have to do a search for the other sampler(s) where the texture is bound to
3924              * Shouldn't happen as long as apps bind a texture only to one stage
3925              */
3926             TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
3927             for(i = 0; i < GL_LIMITS(sampler_stages); i++) {
3928                 if(This->updateStateBlock->textures[i] == oldTexture) {
3929                     old->baseTexture.sampler = i;
3930                     break;
3931                 }
3932             }
3933         }
3934     }
3935
3936     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
3937
3938     /* Verify the texture unit mapping(and rebuild it if needed) if we use nvrcs and no
3939      * pixel shader is used
3940      */
3941     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3942         IWineD3DDeviceImpl_FindTexUnitMap(This);
3943     }
3944
3945     return WINED3D_OK;
3946 }
3947
3948 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3949     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3950     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
3951
3952     *ppTexture=This->stateBlock->textures[Stage];
3953     if (*ppTexture)
3954         IWineD3DBaseTexture_AddRef(*ppTexture);
3955
3956     return WINED3D_OK;
3957 }
3958
3959 /*****
3960  * Get Back Buffer
3961  *****/
3962 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
3963                                                 IWineD3DSurface **ppBackBuffer) {
3964     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3965     IWineD3DSwapChain *swapChain;
3966     HRESULT hr;
3967
3968     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3969
3970     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
3971     if (hr == WINED3D_OK) {
3972         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
3973             IWineD3DSwapChain_Release(swapChain);
3974     } else {
3975         *ppBackBuffer = NULL;
3976     }
3977     return hr;
3978 }
3979
3980 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
3981     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3982     WARN("(%p) : stub, calling idirect3d for now\n", This);
3983     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
3984 }
3985
3986 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
3987     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3988     IWineD3DSwapChain *swapChain;
3989     HRESULT hr;
3990
3991     if(iSwapChain > 0) {
3992         hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
3993         if (hr == WINED3D_OK) {
3994             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
3995             IWineD3DSwapChain_Release(swapChain);
3996         } else {
3997             FIXME("(%p) Error getting display mode\n", This);
3998         }
3999     } else {
4000         /* Don't read the real display mode,
4001            but return the stored mode instead. X11 can't change the color
4002            depth, and some apps are pretty angry if they SetDisplayMode from
4003            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4004
4005            Also don't relay to the swapchain because with ddraw it's possible
4006            that there isn't a swapchain at all */
4007         pMode->Width = This->ddraw_width;
4008         pMode->Height = This->ddraw_height;
4009         pMode->Format = This->ddraw_format;
4010         pMode->RefreshRate = 0;
4011         hr = WINED3D_OK;
4012     }
4013
4014     return hr;
4015 }
4016
4017 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
4018     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4019     TRACE("(%p)->(%p)\n", This, hWnd);
4020
4021     if(This->ddraw_fullscreen) {
4022         if(This->ddraw_window && This->ddraw_window != hWnd) {
4023             IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
4024         }
4025         if(hWnd && This->ddraw_window != hWnd) {
4026             IWineD3DDeviceImpl_SetupFullscreenWindow(iface, hWnd);
4027         }
4028     }
4029
4030     This->ddraw_window = hWnd;
4031     return WINED3D_OK;
4032 }
4033
4034 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
4035     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4036     TRACE("(%p)->(%p)\n", This, hWnd);
4037
4038     *hWnd = This->ddraw_window;
4039     return WINED3D_OK;
4040 }
4041
4042 /*****
4043  * Stateblock related functions
4044  *****/
4045
4046 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4047     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4048     IWineD3DStateBlockImpl *object;
4049     HRESULT temp_result;
4050     int i;
4051
4052     TRACE("(%p)\n", This);
4053     
4054     if (This->isRecordingState) {
4055         return WINED3DERR_INVALIDCALL;
4056     }
4057     
4058     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4059     if (NULL == object ) {
4060         FIXME("(%p)Error allocating memory for stateblock\n", This);
4061         return E_OUTOFMEMORY;
4062     }
4063     TRACE("(%p) created object %p\n", This, object);
4064     object->wineD3DDevice= This;
4065     /** FIXME: object->parent       = parent; **/
4066     object->parent       = NULL;
4067     object->blockType    = WINED3DSBT_ALL;
4068     object->ref          = 1;
4069     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4070
4071     for(i = 0; i < LIGHTMAP_SIZE; i++) {
4072         list_init(&object->lightMap[i]);
4073     }
4074
4075     temp_result = allocate_shader_constants(object);
4076     if (WINED3D_OK != temp_result)
4077         return temp_result;
4078
4079     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4080     This->updateStateBlock = object;
4081     This->isRecordingState = TRUE;
4082
4083     TRACE("(%p) recording stateblock %p\n",This , object);
4084     return WINED3D_OK;
4085 }
4086
4087 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4088     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4089
4090     if (!This->isRecordingState) {
4091         FIXME("(%p) not recording! returning error\n", This);
4092         *ppStateBlock = NULL;
4093         return WINED3DERR_INVALIDCALL;
4094     }
4095
4096     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4097     This->isRecordingState = FALSE;
4098     This->updateStateBlock = This->stateBlock;
4099     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4100     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4101     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4102     return WINED3D_OK;
4103 }
4104
4105 /*****
4106  * Scene related functions
4107  *****/
4108 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4109     /* At the moment we have no need for any functionality at the beginning
4110        of a scene                                                          */
4111     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4112     TRACE("(%p)\n", This);
4113
4114     if(This->inScene) {
4115         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4116         return WINED3DERR_INVALIDCALL;
4117     }
4118     This->inScene = TRUE;
4119     return WINED3D_OK;
4120 }
4121
4122 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4123     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4124     TRACE("(%p)\n", This);
4125
4126     if(!This->inScene) {
4127         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4128         return WINED3DERR_INVALIDCALL;
4129     }
4130
4131     ENTER_GL();
4132     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4133     glFlush();
4134     checkGLcall("glFlush");
4135     LEAVE_GL();
4136
4137     This->inScene = FALSE;
4138     return WINED3D_OK;
4139 }
4140
4141 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4142                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4143                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4144     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4145     IWineD3DSwapChain *swapChain = NULL;
4146     int i;
4147     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4148
4149     TRACE("(%p) Presenting the frame\n", This);
4150
4151     for(i = 0 ; i < swapchains ; i ++) {
4152
4153         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4154         TRACE("presentinng chain %d, %p\n", i, swapChain);
4155         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4156         IWineD3DSwapChain_Release(swapChain);
4157     }
4158
4159     return WINED3D_OK;
4160 }
4161
4162 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4163                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4164     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4165
4166     /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the
4167       render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag
4168       when the depth-buffer format does not contain stencil buffer information, this method fails. */
4169     GLbitfield     glMask = 0;
4170     unsigned int   i;
4171     CONST WINED3DRECT* curRect;
4172
4173     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
4174           Count, pRects, Flags, Z, Stencil);
4175
4176     ENTER_GL();
4177
4178     if(pRects) {
4179         glEnable(GL_SCISSOR_TEST);
4180         checkGLcall("glEnable GL_SCISSOR_TEST");
4181         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
4182     } else {
4183         glDisable(GL_SCISSOR_TEST);
4184         checkGLcall("glEnable GL_SCISSOR_TEST");
4185     }
4186     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
4187
4188     if (Count > 0 && pRects) {
4189         curRect = pRects;
4190     } else {
4191         curRect = NULL;
4192     }
4193
4194     /* Only set the values up once, as they are not changing */
4195     if (Flags & WINED3DCLEAR_STENCIL) {
4196         glClearStencil(Stencil);
4197         checkGLcall("glClearStencil");
4198         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4199         glStencilMask(0xFFFFFFFF);
4200     }
4201
4202     if (Flags & WINED3DCLEAR_ZBUFFER) {
4203         glDepthMask(GL_TRUE);
4204         glClearDepth(Z);
4205         checkGLcall("glClearDepth");
4206         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4207         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4208     }
4209
4210     if (Flags & WINED3DCLEAR_TARGET) {
4211         TRACE("Clearing screen with glClear to color %x\n", Color);
4212         glClearColor(D3DCOLOR_R(Color),
4213                      D3DCOLOR_G(Color),
4214                      D3DCOLOR_B(Color),
4215                      D3DCOLOR_A(Color));
4216         checkGLcall("glClearColor");
4217
4218         /* Clear ALL colors! */
4219         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4220         glMask = glMask | GL_COLOR_BUFFER_BIT;
4221     }
4222
4223     /* Now process each rect in turn */
4224     for (i = 0; i < Count || i == 0; i++) {
4225
4226         if (curRect) {
4227             /* Note gl uses lower left, width/height */
4228             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4229                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4230                   curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4231                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4232             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4233                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4234             checkGLcall("glScissor");
4235         }
4236
4237         /* Clear the selected rectangle (or full screen) */
4238         glClear(glMask);
4239         checkGLcall("glClear");
4240
4241         /* Step to the next rectangle */
4242         if (curRect) curRect = curRect + sizeof(WINED3DRECT);
4243     }
4244
4245     /* Restore the old values (why..?) */
4246     if (Flags & WINED3DCLEAR_STENCIL) {
4247         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4248     }
4249     if (Flags & WINED3DCLEAR_TARGET) {
4250         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4251                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4252                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4253                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4254     }
4255
4256     LEAVE_GL();
4257
4258     /* Dirtify the target surface for now. If the surface is locked regularily, and an up to date sysmem copy exists,
4259      * it is most likely more efficient to perform a clear on the sysmem copy too isntead of downloading it
4260      */
4261     ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags |= SFLAG_GLDIRTY;
4262     return WINED3D_OK;
4263 }
4264
4265 /*****
4266  * Drawing functions
4267  *****/
4268 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4269                                                 UINT PrimitiveCount) {
4270
4271     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4272     This->stateBlock->streamIsUP = FALSE;
4273
4274     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4275                                debug_d3dprimitivetype(PrimitiveType),
4276                                StartVertex, PrimitiveCount);
4277
4278     if(This->stateBlock->loadBaseVertexIndex != 0) {
4279         This->stateBlock->loadBaseVertexIndex = 0;
4280         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4281     }
4282     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4283     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4284                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4285     return WINED3D_OK;
4286 }
4287
4288 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4289 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4290                                                            WINED3DPRIMITIVETYPE PrimitiveType,
4291                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4292
4293     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4294     UINT                 idxStride = 2;
4295     IWineD3DIndexBuffer *pIB;
4296     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
4297     GLuint vbo;
4298
4299     pIB = This->stateBlock->pIndexData;
4300     This->stateBlock->streamIsUP = FALSE;
4301     vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
4302
4303     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
4304           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4305           minIndex, NumVertices, startIndex, primCount);
4306
4307     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4308     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4309         idxStride = 2;
4310     } else {
4311         idxStride = 4;
4312     }
4313
4314     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4315         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4316         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4317     }
4318
4319     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
4320                    idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4321
4322     return WINED3D_OK;
4323 }
4324
4325 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4326                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4327                                                     UINT VertexStreamZeroStride) {
4328     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4329
4330     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4331              debug_d3dprimitivetype(PrimitiveType),
4332              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4333
4334     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4335     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4336     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4337     This->stateBlock->streamIsUP = TRUE;
4338     This->stateBlock->loadBaseVertexIndex = 0;
4339
4340     /* TODO: Only mark dirty if drawing from a different UP address */
4341     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4342
4343     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4344                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4345
4346     /* MSDN specifies stream zero settings must be set to NULL */
4347     This->stateBlock->streamStride[0] = 0;
4348     This->stateBlock->streamSource[0] = NULL;
4349
4350     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4351      * the new stream sources or use UP drawing again
4352      */
4353     return WINED3D_OK;
4354 }
4355
4356 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4357                                                              UINT MinVertexIndex, UINT NumVertices,
4358                                                              UINT PrimitiveCount, CONST void* pIndexData,
4359                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4360                                                              UINT VertexStreamZeroStride) {
4361     int                 idxStride;
4362     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4363
4364     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4365              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4366              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4367              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4368
4369     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4370         idxStride = 2;
4371     } else {
4372         idxStride = 4;
4373     }
4374
4375     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4376     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4377     This->stateBlock->streamIsUP = TRUE;
4378     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4379
4380     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4381     This->stateBlock->baseVertexIndex = 0;
4382     This->stateBlock->loadBaseVertexIndex = 0;
4383     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4384     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4385     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4386
4387     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4388
4389     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4390     This->stateBlock->streamSource[0] = NULL;
4391     This->stateBlock->streamStride[0] = 0;
4392     This->stateBlock->pIndexData = NULL;
4393     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4394      * SetStreamSource to specify a vertex buffer
4395      */
4396
4397     return WINED3D_OK;
4398 }
4399
4400 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4401     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4402
4403     /* Mark the state dirty until we have nicer tracking
4404      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4405      * that value.
4406      */
4407     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4408     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4409     This->stateBlock->baseVertexIndex = 0;
4410     This->up_strided = DrawPrimStrideData;
4411     This->stateBlock->streamIsUP = TRUE;
4412     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
4413     This->up_strided = NULL;
4414     return WINED3D_OK;
4415 }
4416  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4417 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4418     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4419     HRESULT hr = WINED3D_OK;
4420     WINED3DRESOURCETYPE sourceType;
4421     WINED3DRESOURCETYPE destinationType;
4422     int i ,levels;
4423
4424     /* TODO: think about moving the code into IWineD3DBaseTexture  */
4425
4426     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4427
4428     /* verify that the source and destination textures aren't NULL */
4429     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4430         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4431              This, pSourceTexture, pDestinationTexture);
4432         hr = WINED3DERR_INVALIDCALL;
4433     }
4434
4435     if (pSourceTexture == pDestinationTexture) {
4436         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4437              This, pSourceTexture, pDestinationTexture);
4438         hr = WINED3DERR_INVALIDCALL;
4439     }
4440     /* Verify that the source and destination textures are the same type */
4441     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
4442     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4443
4444     if (sourceType != destinationType) {
4445         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
4446              This);
4447         hr = WINED3DERR_INVALIDCALL;
4448     }
4449
4450     /* check that both textures have the identical numbers of levels  */
4451     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4452         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4453         hr = WINED3DERR_INVALIDCALL;
4454     }
4455
4456     if (WINED3D_OK == hr) {
4457
4458         /* Make sure that the destination texture is loaded */
4459         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4460
4461         /* Update every surface level of the texture */
4462         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4463
4464         switch (sourceType) {
4465         case WINED3DRTYPE_TEXTURE:
4466             {
4467                 IWineD3DSurface *srcSurface;
4468                 IWineD3DSurface *destSurface;
4469
4470                 for (i = 0 ; i < levels ; ++i) {
4471                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
4472                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4473                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4474                     IWineD3DSurface_Release(srcSurface);
4475                     IWineD3DSurface_Release(destSurface);
4476                     if (WINED3D_OK != hr) {
4477                         WARN("(%p) : Call to update surface failed\n", This);
4478                         return hr;
4479                     }
4480                 }
4481             }
4482             break;
4483         case WINED3DRTYPE_CUBETEXTURE:
4484             {
4485                 IWineD3DSurface *srcSurface;
4486                 IWineD3DSurface *destSurface;
4487                 WINED3DCUBEMAP_FACES faceType;
4488
4489                 for (i = 0 ; i < levels ; ++i) {
4490                     /* Update each cube face */
4491                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4492                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
4493                         if (WINED3D_OK != hr) {
4494                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4495                         } else {
4496                             TRACE("Got srcSurface %p\n", srcSurface);
4497                         }
4498                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4499                         if (WINED3D_OK != hr) {
4500                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4501                         } else {
4502                             TRACE("Got desrSurface %p\n", destSurface);
4503                         }
4504                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4505                         IWineD3DSurface_Release(srcSurface);
4506                         IWineD3DSurface_Release(destSurface);
4507                         if (WINED3D_OK != hr) {
4508                             WARN("(%p) : Call to update surface failed\n", This);
4509                             return hr;
4510                         }
4511                     }
4512                 }
4513             }
4514             break;
4515 #if 0 /* TODO: Add support for volume textures */
4516         case WINED3DRTYPE_VOLUMETEXTURE:
4517             {
4518                 IWineD3DVolume  srcVolume  = NULL;
4519                 IWineD3DSurface destVolume = NULL;
4520
4521                 for (i = 0 ; i < levels ; ++i) {
4522                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
4523                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4524                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4525                     IWineD3DVolume_Release(srcSurface);
4526                     IWineD3DVolume_Release(destSurface);
4527                     if (WINED3D_OK != hr) {
4528                         WARN("(%p) : Call to update volume failed\n", This);
4529                         return hr;
4530                     }
4531                 }
4532             }
4533             break;
4534 #endif
4535         default:
4536             FIXME("(%p) : Unsupported source and destination type\n", This);
4537             hr = WINED3DERR_INVALIDCALL;
4538         }
4539     }
4540
4541     return hr;
4542 }
4543
4544 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4545     IWineD3DSwapChain *swapChain;
4546     HRESULT hr;
4547     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4548     if(hr == WINED3D_OK) {
4549         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4550                 IWineD3DSwapChain_Release(swapChain);
4551     }
4552     return hr;
4553 }
4554
4555 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4556     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4557     /* return a sensible default */
4558     *pNumPasses = 1;
4559     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
4560     FIXME("(%p) : stub\n", This);
4561     return WINED3D_OK;
4562 }
4563
4564 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4565     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4566     int j;
4567     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4568     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4569         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4570         return WINED3DERR_INVALIDCALL;
4571     }
4572     for (j = 0; j < 256; ++j) {
4573         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
4574         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4575         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
4576         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4577     }
4578     TRACE("(%p) : returning\n", This);
4579     return WINED3D_OK;
4580 }
4581
4582 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4583     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4584     int j;
4585     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4586     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4587         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4588         return WINED3DERR_INVALIDCALL;
4589     }
4590     for (j = 0; j < 256; ++j) {
4591         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
4592         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4593         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
4594         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4595     }
4596     TRACE("(%p) : returning\n", This);
4597     return WINED3D_OK;
4598 }
4599
4600 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4601     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4602     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4603     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4604         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4605         return WINED3DERR_INVALIDCALL;
4606     }
4607     /*TODO: stateblocks */
4608     This->currentPalette = PaletteNumber;
4609     TRACE("(%p) : returning\n", This);
4610     return WINED3D_OK;
4611 }
4612
4613 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4614     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4615     if (PaletteNumber == NULL) {
4616         WARN("(%p) : returning Invalid Call\n", This);
4617         return WINED3DERR_INVALIDCALL;
4618     }
4619     /*TODO: stateblocks */
4620     *PaletteNumber = This->currentPalette;
4621     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
4622     return WINED3D_OK;
4623 }
4624
4625 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4626     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4627     static BOOL showFixmes = TRUE;
4628     if (showFixmes) {
4629         FIXME("(%p) : stub\n", This);
4630         showFixmes = FALSE;
4631     }
4632
4633     This->softwareVertexProcessing = bSoftware;
4634     return WINED3D_OK;
4635 }
4636
4637
4638 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4639     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4640     static BOOL showFixmes = TRUE;
4641     if (showFixmes) {
4642         FIXME("(%p) : stub\n", This);
4643         showFixmes = FALSE;
4644     }
4645     return This->softwareVertexProcessing;
4646 }
4647
4648
4649 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
4650     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4651     IWineD3DSwapChain *swapChain;
4652     HRESULT hr;
4653
4654     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4655
4656     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4657     if(hr == WINED3D_OK){
4658         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4659         IWineD3DSwapChain_Release(swapChain);
4660     }else{
4661         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
4662     }
4663     return hr;
4664 }
4665
4666
4667 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4668     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4669     static BOOL showfixmes = TRUE;
4670     if(nSegments != 0.0f) {
4671         if( showfixmes) {
4672             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4673             showfixmes = FALSE;
4674         }
4675     }
4676     return WINED3D_OK;
4677 }
4678
4679 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4680     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4681     static BOOL showfixmes = TRUE;
4682     if( showfixmes) {
4683         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4684         showfixmes = FALSE;
4685     }
4686     return 0.0f;
4687 }
4688
4689 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4690     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
4691     /** TODO: remove casts to IWineD3DSurfaceImpl
4692      *       NOTE: move code to surface to accomplish this
4693       ****************************************/
4694     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
4695     int srcWidth, srcHeight;
4696     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4697     WINED3DFORMAT destFormat, srcFormat;
4698     UINT          destSize;
4699     int srcLeft, destLeft, destTop;
4700     WINED3DPOOL       srcPool, destPool;
4701     int offset    = 0;
4702     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4703     glDescriptor *glDescription = NULL;
4704
4705     WINED3DSURFACE_DESC  winedesc;
4706
4707     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
4708     memset(&winedesc, 0, sizeof(winedesc));
4709     winedesc.Width  = &srcSurfaceWidth;
4710     winedesc.Height = &srcSurfaceHeight;
4711     winedesc.Pool   = &srcPool;
4712     winedesc.Format = &srcFormat;
4713
4714     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4715
4716     winedesc.Width  = &destSurfaceWidth;
4717     winedesc.Height = &destSurfaceHeight;
4718     winedesc.Pool   = &destPool;
4719     winedesc.Format = &destFormat;
4720     winedesc.Size   = &destSize;
4721
4722     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4723
4724     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
4725         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
4726         return WINED3DERR_INVALIDCALL;
4727     }
4728
4729     if (destFormat == WINED3DFMT_UNKNOWN) {
4730         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
4731         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
4732
4733         /* Get the update surface description */
4734         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4735     }
4736
4737     ENTER_GL();
4738     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4739         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
4740         checkGLcall("glActiveTextureARB");
4741     }
4742
4743     /* Make sure the surface is loaded and up to date */
4744     IWineD3DSurface_PreLoad(pDestinationSurface);
4745
4746     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4747
4748     /* this needs to be done in lines if the sourceRect != the sourceWidth */
4749     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
4750     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
4751     srcLeft    = pSourceRect ? pSourceRect->left : 0;
4752     destLeft   = pDestPoint  ? pDestPoint->x : 0;
4753     destTop    = pDestPoint  ? pDestPoint->y : 0;
4754
4755
4756     /* This function doesn't support compressed textures
4757     the pitch is just bytesPerPixel * width */
4758     if(srcWidth != srcSurfaceWidth  || srcLeft ){
4759         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4760         offset   += srcLeft * pSrcSurface->bytesPerPixel;
4761         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4762     }
4763     /* TODO DXT formats */
4764
4765     if(pSourceRect != NULL && pSourceRect->top != 0){
4766        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4767     }
4768     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4769     ,This
4770     ,glDescription->level
4771     ,destLeft
4772     ,destTop
4773     ,srcWidth
4774     ,srcHeight
4775     ,glDescription->glFormat
4776     ,glDescription->glType
4777     ,IWineD3DSurface_GetData(pSourceSurface)
4778     );
4779
4780     /* Sanity check */
4781     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4782
4783         /* need to lock the surface to get the data */
4784         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4785     }
4786
4787     /* TODO: Cube and volume support */
4788     if(rowoffset != 0){
4789         /* not a whole row so we have to do it a line at a time */
4790         int j;
4791
4792         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4793         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4794
4795         for(j = destTop ; j < (srcHeight + destTop) ; j++){
4796
4797                 glTexSubImage2D(glDescription->target
4798                     ,glDescription->level
4799                     ,destLeft
4800                     ,j
4801                     ,srcWidth
4802                     ,1
4803                     ,glDescription->glFormat
4804                     ,glDescription->glType
4805                     ,data /* could be quicker using */
4806                 );
4807             data += rowoffset;
4808         }
4809
4810     } else { /* Full width, so just write out the whole texture */
4811
4812         if (WINED3DFMT_DXT1 == destFormat ||
4813             WINED3DFMT_DXT2 == destFormat ||
4814             WINED3DFMT_DXT3 == destFormat ||
4815             WINED3DFMT_DXT4 == destFormat ||
4816             WINED3DFMT_DXT5 == destFormat) {
4817             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4818                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4819                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
4820                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
4821                 } if (destFormat != srcFormat) {
4822                     FIXME("Updating mixed format compressed texture is not curretly support\n");
4823                 } else {
4824                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4825                                                         glDescription->level,
4826                                                         glDescription->glFormatInternal,
4827                                                         srcWidth,
4828                                                         srcHeight,
4829                                                         0,
4830                                                         destSize,
4831                                                         IWineD3DSurface_GetData(pSourceSurface));
4832                 }
4833             } else {
4834                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4835             }
4836
4837
4838         } else {
4839             glTexSubImage2D(glDescription->target
4840                     ,glDescription->level
4841                     ,destLeft
4842                     ,destTop
4843                     ,srcWidth
4844                     ,srcHeight
4845                     ,glDescription->glFormat
4846                     ,glDescription->glType
4847                     ,IWineD3DSurface_GetData(pSourceSurface)
4848                 );
4849         }
4850      }
4851     checkGLcall("glTexSubImage2D");
4852
4853     LEAVE_GL();
4854
4855     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
4856     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
4857
4858     return WINED3D_OK;
4859 }
4860
4861 /* Implementation details at http://developer.nvidia.com/attach/6494
4862 and
4863 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4864 hmm.. no longer supported use
4865 OpenGL evaluators or  tessellate surfaces within your application.
4866 */
4867
4868 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4869 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
4870     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4871     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
4872     FIXME("(%p) : Stub\n", This);
4873     return WINED3D_OK;
4874
4875 }
4876
4877 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4878 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
4879     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4880     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
4881     FIXME("(%p) : Stub\n", This);
4882     return WINED3D_OK;
4883 }
4884
4885 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4886     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4887     TRACE("(%p) Handle(%d)\n", This, Handle);
4888     FIXME("(%p) : Stub\n", This);
4889     return WINED3D_OK;
4890 }
4891
4892 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
4893     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4894     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
4895     DDBLTFX BltFx;
4896     TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
4897
4898     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
4899         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
4900         return WINED3DERR_INVALIDCALL;
4901     }
4902
4903     /* Just forward this to the DirectDraw blitting engine */
4904     memset(&BltFx, 0, sizeof(BltFx));
4905     BltFx.dwSize = sizeof(BltFx);
4906     BltFx.u5.dwFillColor = color;
4907     return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
4908 }
4909
4910 /* rendertarget and deptth stencil functions */
4911 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
4912     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4913
4914     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
4915         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
4916         return WINED3DERR_INVALIDCALL;
4917     }
4918
4919     *ppRenderTarget = This->render_targets[RenderTargetIndex];
4920     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4921     /* Note inc ref on returned surface */
4922     if(*ppRenderTarget != NULL)
4923         IWineD3DSurface_AddRef(*ppRenderTarget);
4924     return WINED3D_OK;
4925 }
4926
4927 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
4928     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4929     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
4930     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
4931     IWineD3DSwapChainImpl *Swapchain;
4932     HRESULT hr;
4933
4934     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
4935
4936     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
4937     if(hr != WINED3D_OK) {
4938         ERR("Can't get the swapchain\n");
4939         return hr;
4940     }
4941
4942     /* Make sure to release the swapchain */
4943     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
4944
4945     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
4946         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
4947         return WINED3DERR_INVALIDCALL;
4948     }
4949     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
4950         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
4951         return WINED3DERR_INVALIDCALL;
4952     }
4953
4954     if(Swapchain->frontBuffer != Front) {
4955         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
4956
4957         if(Swapchain->frontBuffer)
4958             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
4959         Swapchain->frontBuffer = Front;
4960
4961         if(Swapchain->frontBuffer) {
4962             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
4963         }
4964     }
4965
4966     if(Back && !Swapchain->backBuffer) {
4967         /* We need memory for the back buffer array - only one back buffer this way */
4968         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
4969         if(!Swapchain->backBuffer) {
4970             ERR("Out of memory\n");
4971             return E_OUTOFMEMORY;
4972         }
4973     }
4974
4975     if(Swapchain->backBuffer[0] != Back) {
4976         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
4977         ENTER_GL();
4978         if(!Swapchain->backBuffer[0]) {
4979             /* GL was told to draw to the front buffer at creation,
4980              * undo that
4981              */
4982             glDrawBuffer(GL_BACK);
4983             checkGLcall("glDrawBuffer(GL_BACK)");
4984             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
4985             Swapchain->presentParms.BackBufferCount = 1;
4986         } else if (!Back) {
4987             /* That makes problems - disable for now */
4988             /* glDrawBuffer(GL_FRONT); */
4989             checkGLcall("glDrawBuffer(GL_FRONT)");
4990             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
4991             Swapchain->presentParms.BackBufferCount = 0;
4992         }
4993         LEAVE_GL();
4994
4995         if(Swapchain->backBuffer[0])
4996             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
4997         Swapchain->backBuffer[0] = Back;
4998
4999         if(Swapchain->backBuffer[0]) {
5000             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
5001         } else {
5002             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
5003         }
5004
5005     }
5006
5007     return WINED3D_OK;
5008 }
5009
5010 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5011     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5012     *ppZStencilSurface = This->depthStencilBuffer;
5013     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5014
5015     if(*ppZStencilSurface != NULL) {
5016         /* Note inc ref on returned surface */
5017         IWineD3DSurface_AddRef(*ppZStencilSurface);
5018     }
5019     return WINED3D_OK;
5020 }
5021
5022 static void bind_fbo(IWineD3DDevice *iface) {
5023     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5024
5025     if (!This->fbo) {
5026         GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
5027         checkGLcall("glGenFramebuffersEXT()");
5028     }
5029     GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
5030     checkGLcall("glBindFramebuffer()");
5031 }
5032
5033 /* TODO: Handle stencil attachments */
5034 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5035     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5036     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5037
5038     This->depth_copy_state = WINED3D_DCS_NO_COPY;
5039
5040     bind_fbo(iface);
5041
5042     if (depth_stencil_impl) {
5043         GLenum texttarget, target;
5044         GLint old_binding = 0;
5045
5046         IWineD3DSurface_PreLoad(depth_stencil);
5047         texttarget = depth_stencil_impl->glDescription.target;
5048         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5049
5050         glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5051         glBindTexture(target, depth_stencil_impl->glDescription.textureName);
5052         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5053         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5054         glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5055         glBindTexture(target, old_binding);
5056
5057         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5058         checkGLcall("glFramebufferTexture2DEXT()");
5059     } else {
5060         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5061         checkGLcall("glFramebufferTexture2DEXT()");
5062     }
5063
5064     if (!This->render_offscreen) {
5065         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5066         checkGLcall("glBindFramebuffer()");
5067     }
5068 }
5069
5070 void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5071     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5072     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5073
5074     if (idx >= GL_LIMITS(buffers)) {
5075         ERR("%p : Trying to set render target %d, but only %d supported\n", This, idx, GL_LIMITS(buffers));
5076     }
5077
5078     bind_fbo(iface);
5079
5080     if (rtimpl) {
5081         GLenum texttarget, target;
5082         GLint old_binding = 0;
5083
5084         IWineD3DSurface_PreLoad(render_target);
5085         texttarget = rtimpl->glDescription.target;
5086         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5087
5088         glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5089         glBindTexture(target, rtimpl->glDescription.textureName);
5090         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5091         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5092         glBindTexture(target, old_binding);
5093
5094         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, rtimpl->glDescription.textureName, 0));
5095         checkGLcall("glFramebufferTexture2DEXT()");
5096
5097         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5098     } else {
5099         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5100         checkGLcall("glFramebufferTexture2DEXT()");
5101
5102         This->draw_buffers[idx] = GL_NONE;
5103     }
5104
5105     if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5106         GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5107         checkGLcall("glDrawBuffers()");
5108     }
5109
5110     if (!This->render_offscreen) {
5111         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5112         checkGLcall("glBindFramebuffer()");
5113     }
5114 }
5115
5116 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5117     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5118     WINED3DVIEWPORT viewport;
5119
5120     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5121
5122     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5123         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5124         return WINED3DERR_INVALIDCALL;
5125     }
5126
5127     /* MSDN says that null disables the render target
5128     but a device must always be associated with a render target
5129     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5130
5131     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5132     for more details
5133     */
5134     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5135         FIXME("Trying to set render target 0 to NULL\n");
5136         return WINED3DERR_INVALIDCALL;
5137     }
5138     if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5139         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);
5140         return WINED3DERR_INVALIDCALL;
5141     }
5142
5143     /* If we are trying to set what we already have, don't bother */
5144     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5145         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5146         return WINED3D_OK;
5147     }
5148     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5149     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5150     This->render_targets[RenderTargetIndex] = pRenderTarget;
5151
5152     /* Render target 0 is special */
5153     if(RenderTargetIndex == 0) {
5154         /* Finally, reset the viewport as the MSDN states. */
5155         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5156         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5157         viewport.X      = 0;
5158         viewport.Y      = 0;
5159         viewport.MaxZ   = 1.0f;
5160         viewport.MinZ   = 0.0f;
5161         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5162
5163         /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
5164          * ctx properly.
5165          * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
5166          * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
5167          */
5168         ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
5169     } else {
5170         /* We only get more than 1 render target with fbos, so no need to check the offscreen rendering method */
5171         set_render_target_fbo(iface, RenderTargetIndex, pRenderTarget);
5172     }
5173     return WINED3D_OK;
5174 }
5175
5176 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5177     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5178     HRESULT  hr = WINED3D_OK;
5179     IWineD3DSurface *tmp;
5180
5181     TRACE("(%p) Swapping z-buffer\n",This);
5182
5183     if (pNewZStencil == This->stencilBufferTarget) {
5184         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5185     } else {
5186         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5187         * depending on the renter target implementation being used.
5188         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5189         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5190         * stencil buffer and incure an extra memory overhead
5191          ******************************************************/
5192
5193
5194         tmp = This->stencilBufferTarget;
5195         This->stencilBufferTarget = pNewZStencil;
5196         /* should we be calling the parent or the wined3d surface? */
5197         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5198         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5199         hr = WINED3D_OK;
5200         /** TODO: glEnable/glDisable on depth/stencil    depending on
5201          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
5202           **********************************************************/
5203         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5204             set_depth_stencil_fbo(iface, pNewZStencil);
5205         }
5206     }
5207
5208     return hr;
5209 }
5210
5211 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5212                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5213     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5214     /* TODO: the use of Impl is deprecated. */
5215     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5216
5217     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5218
5219     /* some basic validation checks */
5220     if(This->cursorTexture) {
5221         ENTER_GL();
5222         glDeleteTextures(1, &This->cursorTexture);
5223         LEAVE_GL();
5224         This->cursorTexture = 0;
5225     }
5226
5227     if(pCursorBitmap) {
5228         /* MSDN: Cursor must be A8R8G8B8 */
5229         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5230             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5231             return WINED3DERR_INVALIDCALL;
5232         }
5233
5234         /* MSDN: Cursor must be smaller than the display mode */
5235         if(pSur->currentDesc.Width > This->ddraw_width ||
5236            pSur->currentDesc.Height > This->ddraw_height) {
5237             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);
5238             return WINED3DERR_INVALIDCALL;
5239         }
5240
5241         /* TODO: MSDN: Cursor sizes must be a power of 2 */
5242         /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
5243          * Texture and Blitting code to draw the cursor
5244          */
5245         pSur->Flags |= SFLAG_FORCELOAD;
5246         IWineD3DSurface_PreLoad(pCursorBitmap);
5247         pSur->Flags &= ~SFLAG_FORCELOAD;
5248         /* Do not store the surface's pointer because the application may release
5249          * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
5250          * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
5251          */
5252         This->cursorTexture = pSur->glDescription.textureName;
5253         This->cursorWidth = pSur->currentDesc.Width;
5254         This->cursorHeight = pSur->currentDesc.Height;
5255         pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
5256     }
5257
5258     This->xHotSpot = XHotSpot;
5259     This->yHotSpot = YHotSpot;
5260     return WINED3D_OK;
5261 }
5262
5263 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5264     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5265     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5266
5267     This->xScreenSpace = XScreenSpace;
5268     This->yScreenSpace = YScreenSpace;
5269
5270     return;
5271
5272 }
5273
5274 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5275     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5276     BOOL oldVisible = This->bCursorVisible;
5277     TRACE("(%p) : visible(%d)\n", This, bShow);
5278
5279     if(This->cursorTexture)
5280         This->bCursorVisible = bShow;
5281
5282     return oldVisible;
5283 }
5284
5285 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5286     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5287     TRACE("(%p) : state (%u)\n", This, This->state);
5288     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
5289     switch (This->state) {
5290     case WINED3D_OK:
5291         return WINED3D_OK;
5292     case WINED3DERR_DEVICELOST:
5293         {
5294             ResourceList *resourceList  = This->resources;
5295             while (NULL != resourceList) {
5296                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
5297                 return WINED3DERR_DEVICENOTRESET;
5298                 resourceList = resourceList->next;
5299             }
5300             return WINED3DERR_DEVICELOST;
5301         }
5302     case WINED3DERR_DRIVERINTERNALERROR:
5303         return WINED3DERR_DRIVERINTERNALERROR;
5304     }
5305
5306     /* Unknown state */
5307     return WINED3DERR_DRIVERINTERNALERROR;
5308 }
5309
5310
5311 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5312     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5313     /** FIXME: Resource tracking needs to be done,
5314     * The closes we can do to this is set the priorities of all managed textures low
5315     * and then reset them.
5316      ***********************************************************/
5317     FIXME("(%p) : stub\n", This);
5318     return WINED3D_OK;
5319 }
5320
5321 void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5322     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
5323
5324     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
5325     if(surface->Flags & SFLAG_DIBSECTION) {
5326         /* Release the DC */
5327         SelectObject(surface->hDC, surface->dib.holdbitmap);
5328         DeleteDC(surface->hDC);
5329         /* Release the DIB section */
5330         DeleteObject(surface->dib.DIBsection);
5331         surface->dib.bitmap_data = NULL;
5332         surface->resource.allocatedMemory = NULL;
5333         surface->Flags &= ~SFLAG_DIBSECTION;
5334     }
5335     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
5336     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
5337     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
5338         surface->pow2Width = pPresentationParameters->BackBufferWidth;
5339         surface->pow2Height = pPresentationParameters->BackBufferHeight;
5340     } else {
5341         surface->pow2Width = surface->pow2Height = 1;
5342         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
5343         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
5344     }
5345     if(surface->glDescription.textureName) {
5346         ENTER_GL();
5347         glDeleteTextures(1, &surface->glDescription.textureName);
5348         LEAVE_GL();
5349         surface->glDescription.textureName = 0;
5350     }
5351     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
5352        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
5353         surface->Flags |= SFLAG_NONPOW2;
5354     } else  {
5355         surface->Flags &= ~SFLAG_NONPOW2;
5356     }
5357     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
5358     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
5359 }
5360
5361 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5362     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5363     IWineD3DSwapChainImpl *swapchain;
5364     HRESULT hr;
5365     BOOL DisplayModeChanged = FALSE;
5366     WINED3DDISPLAYMODE mode;
5367     TRACE("(%p)\n", This);
5368
5369     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
5370     if(FAILED(hr)) {
5371         ERR("Failed to get the first implicit swapchain\n");
5372         return hr;
5373     }
5374
5375     /* Is it necessary to recreate the gl context? Actually every setting can be changed
5376      * on an existing gl context, so there's no real need for recreation.
5377      *
5378      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
5379      *
5380      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
5381      */
5382     TRACE("New params:\n");
5383     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
5384     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
5385     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
5386     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
5387     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
5388     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
5389     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
5390     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
5391     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
5392     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
5393     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
5394     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
5395     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
5396
5397     /* No special treatment of these parameters. Just store them */
5398     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
5399     swapchain->presentParms.Flags = pPresentationParameters->Flags;
5400     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
5401     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
5402
5403     /* What to do about these? */
5404     if(pPresentationParameters->BackBufferCount != 0 &&
5405         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
5406         ERR("Cannot change the back buffer count yet\n");
5407     }
5408     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
5409         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
5410         ERR("Cannot change the back buffer format yet\n");
5411     }
5412     if(pPresentationParameters->hDeviceWindow != NULL &&
5413         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
5414         ERR("Cannot change the device window yet\n");
5415     }
5416     if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
5417         ERR("What do do about a changed auto depth stencil parameter?\n");
5418     }
5419
5420     if(pPresentationParameters->Windowed) {
5421         mode.Width = swapchain->orig_width;
5422         mode.Height = swapchain->orig_height;
5423         mode.RefreshRate = 0;
5424         mode.Format = swapchain->presentParms.BackBufferFormat;
5425     } else {
5426         mode.Width = pPresentationParameters->BackBufferWidth;
5427         mode.Height = pPresentationParameters->BackBufferHeight;
5428         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
5429         mode.Format = swapchain->presentParms.BackBufferFormat;
5430     }
5431
5432     /* Should Width == 800 && Height == 0 set 800x600? */
5433     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
5434        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
5435         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
5436     {
5437         WINED3DVIEWPORT vp;
5438         int i;
5439
5440         vp.X = 0;
5441         vp.Y = 0;
5442         vp.Width = pPresentationParameters->BackBufferWidth;
5443         vp.Height = pPresentationParameters->BackBufferHeight;
5444         vp.MinZ = 0;
5445         vp.MaxZ = 1;
5446
5447         if(!pPresentationParameters->Windowed) {
5448             DisplayModeChanged = TRUE;
5449         }
5450         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
5451         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
5452
5453         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
5454         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
5455             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
5456         }
5457
5458         /* Now set the new viewport */
5459         IWineD3DDevice_SetViewport(iface, &vp);
5460     }
5461
5462     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
5463        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
5464         DisplayModeChanged) {
5465
5466         /* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */
5467         if(!pPresentationParameters->Windowed) {
5468             IWineD3DDevice_SetFullscreen(iface, TRUE);
5469         }
5470
5471         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
5472
5473         /* Switching out of fullscreen mode? First set the original res, then change the window */
5474         if(pPresentationParameters->Windowed) {
5475             IWineD3DDevice_SetFullscreen(iface, FALSE);
5476         }
5477         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
5478     }
5479
5480     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
5481     return WINED3D_OK;
5482 }
5483
5484 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5485     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5486     /** FIXME: always true at the moment **/
5487     if(!bEnableDialogs) {
5488         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5489     }
5490     return WINED3D_OK;
5491 }
5492
5493
5494 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
5495     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5496     TRACE("(%p) : pParameters %p\n", This, pParameters);
5497
5498     *pParameters = This->createParms;
5499     return WINED3D_OK;
5500 }
5501
5502 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
5503     IWineD3DSwapChain *swapchain;
5504     HRESULT hrc = WINED3D_OK;
5505
5506     TRACE("Relaying  to swapchain\n");
5507
5508     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5509         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
5510         IWineD3DSwapChain_Release(swapchain);
5511     }
5512     return;
5513 }
5514
5515 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
5516     IWineD3DSwapChain *swapchain;
5517     HRESULT hrc = WINED3D_OK;
5518
5519     TRACE("Relaying  to swapchain\n");
5520
5521     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5522         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5523         IWineD3DSwapChain_Release(swapchain);
5524     }
5525     return;
5526 }
5527
5528
5529 /** ********************************************************
5530 *   Notification functions
5531 ** ********************************************************/
5532 /** This function must be called in the release of a resource when ref == 0,
5533 * the contents of resource must still be correct,
5534 * any handels to other resource held by the caller must be closed
5535 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5536  *****************************************************/
5537 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5538     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5539     ResourceList* resourceList;
5540
5541     TRACE("(%p) : resource %p\n", This, resource);
5542 #if 0
5543     EnterCriticalSection(&resourceStoreCriticalSection);
5544 #endif
5545     /* add a new texture to the frot of the linked list */
5546     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5547     resourceList->resource = resource;
5548
5549     /* Get the old head */
5550     resourceList->next = This->resources;
5551
5552     This->resources = resourceList;
5553     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5554
5555 #if 0
5556     LeaveCriticalSection(&resourceStoreCriticalSection);
5557 #endif
5558     return;
5559 }
5560
5561 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5562     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5563     ResourceList* resourceList = NULL;
5564     ResourceList* previousResourceList = NULL;
5565     
5566     TRACE("(%p) : resource %p\n", This, resource);
5567
5568 #if 0
5569     EnterCriticalSection(&resourceStoreCriticalSection);
5570 #endif
5571     resourceList = This->resources;
5572
5573     while (resourceList != NULL) {
5574         if(resourceList->resource == resource) break;
5575         previousResourceList = resourceList;
5576         resourceList = resourceList->next;
5577     }
5578
5579     if (resourceList == NULL) {
5580         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5581 #if 0
5582         LeaveCriticalSection(&resourceStoreCriticalSection);
5583 #endif
5584         return;
5585     } else {
5586             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5587     }
5588     /* make sure we don't leave a hole in the list */
5589     if (previousResourceList != NULL) {
5590         previousResourceList->next = resourceList->next;
5591     } else {
5592         This->resources = resourceList->next;
5593     }
5594
5595 #if 0
5596     LeaveCriticalSection(&resourceStoreCriticalSection);
5597 #endif
5598     return;
5599 }
5600
5601
5602 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5603     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5604     int counter;
5605
5606     TRACE("(%p) : resource %p\n", This, resource);
5607     switch(IWineD3DResource_GetType(resource)){
5608         case WINED3DRTYPE_SURFACE:
5609         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
5610         break;
5611         case WINED3DRTYPE_TEXTURE:
5612         case WINED3DRTYPE_CUBETEXTURE:
5613         case WINED3DRTYPE_VOLUMETEXTURE:
5614                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
5615                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5616                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5617                         This->stateBlock->textures[counter] = NULL;
5618                     }
5619                     if (This->updateStateBlock != This->stateBlock ){
5620                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5621                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5622                             This->updateStateBlock->textures[counter] = NULL;
5623                         }
5624                     }
5625                 }
5626         break;
5627         case WINED3DRTYPE_VOLUME:
5628         /* TODO: nothing really? */
5629         break;
5630         case WINED3DRTYPE_VERTEXBUFFER:
5631         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5632         {
5633             int streamNumber;
5634             TRACE("Cleaning up stream pointers\n");
5635
5636             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5637                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5638                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5639                 */
5640                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5641                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5642                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5643                         This->updateStateBlock->streamSource[streamNumber] = 0;
5644                         /* Set changed flag? */
5645                     }
5646                 }
5647                 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) */
5648                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5649                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5650                         This->stateBlock->streamSource[streamNumber] = 0;
5651                     }
5652                 }
5653 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5654                  else { /* This shouldn't happen */
5655                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5656                 }
5657 #endif
5658
5659             }
5660         }
5661         break;
5662         case WINED3DRTYPE_INDEXBUFFER:
5663         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5664         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5665             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5666                 This->updateStateBlock->pIndexData =  NULL;
5667             }
5668         }
5669         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5670             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5671                 This->stateBlock->pIndexData =  NULL;
5672             }
5673         }
5674
5675         break;
5676         default:
5677         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
5678         break;
5679     }
5680
5681
5682     /* Remove the resoruce from the resourceStore */
5683     IWineD3DDeviceImpl_RemoveResource(iface, resource);
5684
5685     TRACE("Resource released\n");
5686
5687 }
5688
5689 /**********************************************************
5690  * IWineD3DDevice VTbl follows
5691  **********************************************************/
5692
5693 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5694 {
5695     /*** IUnknown methods ***/
5696     IWineD3DDeviceImpl_QueryInterface,
5697     IWineD3DDeviceImpl_AddRef,
5698     IWineD3DDeviceImpl_Release,
5699     /*** IWineD3DDevice methods ***/
5700     IWineD3DDeviceImpl_GetParent,
5701     /*** Creation methods**/
5702     IWineD3DDeviceImpl_CreateVertexBuffer,
5703     IWineD3DDeviceImpl_CreateIndexBuffer,
5704     IWineD3DDeviceImpl_CreateStateBlock,
5705     IWineD3DDeviceImpl_CreateSurface,
5706     IWineD3DDeviceImpl_CreateTexture,
5707     IWineD3DDeviceImpl_CreateVolumeTexture,
5708     IWineD3DDeviceImpl_CreateVolume,
5709     IWineD3DDeviceImpl_CreateCubeTexture,
5710     IWineD3DDeviceImpl_CreateQuery,
5711     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5712     IWineD3DDeviceImpl_CreateVertexDeclaration,
5713     IWineD3DDeviceImpl_CreateVertexShader,
5714     IWineD3DDeviceImpl_CreatePixelShader,
5715     IWineD3DDeviceImpl_CreatePalette,
5716     /*** Odd functions **/
5717     IWineD3DDeviceImpl_Init3D,
5718     IWineD3DDeviceImpl_Uninit3D,
5719     IWineD3DDeviceImpl_SetFullscreen,
5720     IWineD3DDeviceImpl_EvictManagedResources,
5721     IWineD3DDeviceImpl_GetAvailableTextureMem,
5722     IWineD3DDeviceImpl_GetBackBuffer,
5723     IWineD3DDeviceImpl_GetCreationParameters,
5724     IWineD3DDeviceImpl_GetDeviceCaps,
5725     IWineD3DDeviceImpl_GetDirect3D,
5726     IWineD3DDeviceImpl_GetDisplayMode,
5727     IWineD3DDeviceImpl_SetDisplayMode,
5728     IWineD3DDeviceImpl_GetHWND,
5729     IWineD3DDeviceImpl_SetHWND,
5730     IWineD3DDeviceImpl_GetNumberOfSwapChains,
5731     IWineD3DDeviceImpl_GetRasterStatus,
5732     IWineD3DDeviceImpl_GetSwapChain,
5733     IWineD3DDeviceImpl_Reset,
5734     IWineD3DDeviceImpl_SetDialogBoxMode,
5735     IWineD3DDeviceImpl_SetCursorProperties,
5736     IWineD3DDeviceImpl_SetCursorPosition,
5737     IWineD3DDeviceImpl_ShowCursor,
5738     IWineD3DDeviceImpl_TestCooperativeLevel,
5739     /*** Getters and setters **/
5740     IWineD3DDeviceImpl_SetClipPlane,
5741     IWineD3DDeviceImpl_GetClipPlane,
5742     IWineD3DDeviceImpl_SetClipStatus,
5743     IWineD3DDeviceImpl_GetClipStatus,
5744     IWineD3DDeviceImpl_SetCurrentTexturePalette,
5745     IWineD3DDeviceImpl_GetCurrentTexturePalette,
5746     IWineD3DDeviceImpl_SetDepthStencilSurface,
5747     IWineD3DDeviceImpl_GetDepthStencilSurface,
5748     IWineD3DDeviceImpl_SetFVF,
5749     IWineD3DDeviceImpl_GetFVF,
5750     IWineD3DDeviceImpl_SetGammaRamp,
5751     IWineD3DDeviceImpl_GetGammaRamp,
5752     IWineD3DDeviceImpl_SetIndices,
5753     IWineD3DDeviceImpl_GetIndices,
5754     IWineD3DDeviceImpl_SetBasevertexIndex,
5755     IWineD3DDeviceImpl_SetLight,
5756     IWineD3DDeviceImpl_GetLight,
5757     IWineD3DDeviceImpl_SetLightEnable,
5758     IWineD3DDeviceImpl_GetLightEnable,
5759     IWineD3DDeviceImpl_SetMaterial,
5760     IWineD3DDeviceImpl_GetMaterial,
5761     IWineD3DDeviceImpl_SetNPatchMode,
5762     IWineD3DDeviceImpl_GetNPatchMode,
5763     IWineD3DDeviceImpl_SetPaletteEntries,
5764     IWineD3DDeviceImpl_GetPaletteEntries,
5765     IWineD3DDeviceImpl_SetPixelShader,
5766     IWineD3DDeviceImpl_GetPixelShader,
5767     IWineD3DDeviceImpl_SetPixelShaderConstantB,
5768     IWineD3DDeviceImpl_GetPixelShaderConstantB,
5769     IWineD3DDeviceImpl_SetPixelShaderConstantI,
5770     IWineD3DDeviceImpl_GetPixelShaderConstantI,
5771     IWineD3DDeviceImpl_SetPixelShaderConstantF,
5772     IWineD3DDeviceImpl_GetPixelShaderConstantF,
5773     IWineD3DDeviceImpl_SetRenderState,
5774     IWineD3DDeviceImpl_GetRenderState,
5775     IWineD3DDeviceImpl_SetRenderTarget,
5776     IWineD3DDeviceImpl_GetRenderTarget,
5777     IWineD3DDeviceImpl_SetFrontBackBuffers,
5778     IWineD3DDeviceImpl_SetSamplerState,
5779     IWineD3DDeviceImpl_GetSamplerState,
5780     IWineD3DDeviceImpl_SetScissorRect,
5781     IWineD3DDeviceImpl_GetScissorRect,
5782     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5783     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5784     IWineD3DDeviceImpl_SetStreamSource,
5785     IWineD3DDeviceImpl_GetStreamSource,
5786     IWineD3DDeviceImpl_SetStreamSourceFreq,
5787     IWineD3DDeviceImpl_GetStreamSourceFreq,
5788     IWineD3DDeviceImpl_SetTexture,
5789     IWineD3DDeviceImpl_GetTexture,
5790     IWineD3DDeviceImpl_SetTextureStageState,
5791     IWineD3DDeviceImpl_GetTextureStageState,
5792     IWineD3DDeviceImpl_SetTransform,
5793     IWineD3DDeviceImpl_GetTransform,
5794     IWineD3DDeviceImpl_SetVertexDeclaration,
5795     IWineD3DDeviceImpl_GetVertexDeclaration,
5796     IWineD3DDeviceImpl_SetVertexShader,
5797     IWineD3DDeviceImpl_GetVertexShader,
5798     IWineD3DDeviceImpl_SetVertexShaderConstantB,
5799     IWineD3DDeviceImpl_GetVertexShaderConstantB,
5800     IWineD3DDeviceImpl_SetVertexShaderConstantI,
5801     IWineD3DDeviceImpl_GetVertexShaderConstantI,
5802     IWineD3DDeviceImpl_SetVertexShaderConstantF,
5803     IWineD3DDeviceImpl_GetVertexShaderConstantF,
5804     IWineD3DDeviceImpl_SetViewport,
5805     IWineD3DDeviceImpl_GetViewport,
5806     IWineD3DDeviceImpl_MultiplyTransform,
5807     IWineD3DDeviceImpl_ValidateDevice,
5808     IWineD3DDeviceImpl_ProcessVertices,
5809     /*** State block ***/
5810     IWineD3DDeviceImpl_BeginStateBlock,
5811     IWineD3DDeviceImpl_EndStateBlock,
5812     /*** Scene management ***/
5813     IWineD3DDeviceImpl_BeginScene,
5814     IWineD3DDeviceImpl_EndScene,
5815     IWineD3DDeviceImpl_Present,
5816     IWineD3DDeviceImpl_Clear,
5817     /*** Drawing ***/
5818     IWineD3DDeviceImpl_DrawPrimitive,
5819     IWineD3DDeviceImpl_DrawIndexedPrimitive,
5820     IWineD3DDeviceImpl_DrawPrimitiveUP,
5821     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5822     IWineD3DDeviceImpl_DrawPrimitiveStrided,
5823     IWineD3DDeviceImpl_DrawRectPatch,
5824     IWineD3DDeviceImpl_DrawTriPatch,
5825     IWineD3DDeviceImpl_DeletePatch,
5826     IWineD3DDeviceImpl_ColorFill,
5827     IWineD3DDeviceImpl_UpdateTexture,
5828     IWineD3DDeviceImpl_UpdateSurface,
5829     IWineD3DDeviceImpl_GetFrontBufferData,
5830     /*** object tracking ***/
5831     IWineD3DDeviceImpl_ResourceReleased
5832 };
5833
5834
5835 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5836     WINED3DRS_ALPHABLENDENABLE   ,
5837     WINED3DRS_ALPHAFUNC          ,
5838     WINED3DRS_ALPHAREF           ,
5839     WINED3DRS_ALPHATESTENABLE    ,
5840     WINED3DRS_BLENDOP            ,
5841     WINED3DRS_COLORWRITEENABLE   ,
5842     WINED3DRS_DESTBLEND          ,
5843     WINED3DRS_DITHERENABLE       ,
5844     WINED3DRS_FILLMODE           ,
5845     WINED3DRS_FOGDENSITY         ,
5846     WINED3DRS_FOGEND             ,
5847     WINED3DRS_FOGSTART           ,
5848     WINED3DRS_LASTPIXEL          ,
5849     WINED3DRS_SHADEMODE          ,
5850     WINED3DRS_SRCBLEND           ,
5851     WINED3DRS_STENCILENABLE      ,
5852     WINED3DRS_STENCILFAIL        ,
5853     WINED3DRS_STENCILFUNC        ,
5854     WINED3DRS_STENCILMASK        ,
5855     WINED3DRS_STENCILPASS        ,
5856     WINED3DRS_STENCILREF         ,
5857     WINED3DRS_STENCILWRITEMASK   ,
5858     WINED3DRS_STENCILZFAIL       ,
5859     WINED3DRS_TEXTUREFACTOR      ,
5860     WINED3DRS_WRAP0              ,
5861     WINED3DRS_WRAP1              ,
5862     WINED3DRS_WRAP2              ,
5863     WINED3DRS_WRAP3              ,
5864     WINED3DRS_WRAP4              ,
5865     WINED3DRS_WRAP5              ,
5866     WINED3DRS_WRAP6              ,
5867     WINED3DRS_WRAP7              ,
5868     WINED3DRS_ZENABLE            ,
5869     WINED3DRS_ZFUNC              ,
5870     WINED3DRS_ZWRITEENABLE
5871 };
5872
5873 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5874     WINED3DTSS_ADDRESSW              ,
5875     WINED3DTSS_ALPHAARG0             ,
5876     WINED3DTSS_ALPHAARG1             ,
5877     WINED3DTSS_ALPHAARG2             ,
5878     WINED3DTSS_ALPHAOP               ,
5879     WINED3DTSS_BUMPENVLOFFSET        ,
5880     WINED3DTSS_BUMPENVLSCALE         ,
5881     WINED3DTSS_BUMPENVMAT00          ,
5882     WINED3DTSS_BUMPENVMAT01          ,
5883     WINED3DTSS_BUMPENVMAT10          ,
5884     WINED3DTSS_BUMPENVMAT11          ,
5885     WINED3DTSS_COLORARG0             ,
5886     WINED3DTSS_COLORARG1             ,
5887     WINED3DTSS_COLORARG2             ,
5888     WINED3DTSS_COLOROP               ,
5889     WINED3DTSS_RESULTARG             ,
5890     WINED3DTSS_TEXCOORDINDEX         ,
5891     WINED3DTSS_TEXTURETRANSFORMFLAGS
5892 };
5893
5894 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5895     WINED3DSAMP_ADDRESSU         ,
5896     WINED3DSAMP_ADDRESSV         ,
5897     WINED3DSAMP_ADDRESSW         ,
5898     WINED3DSAMP_BORDERCOLOR      ,
5899     WINED3DSAMP_MAGFILTER        ,
5900     WINED3DSAMP_MINFILTER        ,
5901     WINED3DSAMP_MIPFILTER        ,
5902     WINED3DSAMP_MIPMAPLODBIAS    ,
5903     WINED3DSAMP_MAXMIPLEVEL      ,
5904     WINED3DSAMP_MAXANISOTROPY    ,
5905     WINED3DSAMP_SRGBTEXTURE      ,
5906     WINED3DSAMP_ELEMENTINDEX
5907 };
5908
5909 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5910     WINED3DRS_AMBIENT                       ,
5911     WINED3DRS_AMBIENTMATERIALSOURCE         ,
5912     WINED3DRS_CLIPPING                      ,
5913     WINED3DRS_CLIPPLANEENABLE               ,
5914     WINED3DRS_COLORVERTEX                   ,
5915     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
5916     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
5917     WINED3DRS_FOGDENSITY                    ,
5918     WINED3DRS_FOGEND                        ,
5919     WINED3DRS_FOGSTART                      ,
5920     WINED3DRS_FOGTABLEMODE                  ,
5921     WINED3DRS_FOGVERTEXMODE                 ,
5922     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
5923     WINED3DRS_LIGHTING                      ,
5924     WINED3DRS_LOCALVIEWER                   ,
5925     WINED3DRS_MULTISAMPLEANTIALIAS          ,
5926     WINED3DRS_MULTISAMPLEMASK               ,
5927     WINED3DRS_NORMALIZENORMALS              ,
5928     WINED3DRS_PATCHEDGESTYLE                ,
5929     WINED3DRS_POINTSCALE_A                  ,
5930     WINED3DRS_POINTSCALE_B                  ,
5931     WINED3DRS_POINTSCALE_C                  ,
5932     WINED3DRS_POINTSCALEENABLE              ,
5933     WINED3DRS_POINTSIZE                     ,
5934     WINED3DRS_POINTSIZE_MAX                 ,
5935     WINED3DRS_POINTSIZE_MIN                 ,
5936     WINED3DRS_POINTSPRITEENABLE             ,
5937     WINED3DRS_RANGEFOGENABLE                ,
5938     WINED3DRS_SPECULARMATERIALSOURCE        ,
5939     WINED3DRS_TWEENFACTOR                   ,
5940     WINED3DRS_VERTEXBLEND
5941 };
5942
5943 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5944     WINED3DTSS_TEXCOORDINDEX         ,
5945     WINED3DTSS_TEXTURETRANSFORMFLAGS
5946 };
5947
5948 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5949     WINED3DSAMP_DMAPOFFSET
5950 };
5951
5952 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
5953     DWORD rep = StateTable[state].representative;
5954     DWORD idx;
5955     BYTE shift;
5956     UINT i;
5957     WineD3DContext *context;
5958
5959     if(!rep) return;
5960     for(i = 0; i < This->numContexts; i++) {
5961         context = This->contexts[i];
5962         if(isStateDirty(context, rep)) continue;
5963
5964         context->dirtyArray[context->numDirtyEntries++] = rep;
5965         idx = rep >> 5;
5966         shift = rep & 0x1f;
5967         context->isStateDirty[idx] |= (1 << shift);
5968     }
5969 }