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