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