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