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