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