wined3d: Better tracking of vertex buffer assignments.
[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         InterlockedIncrement(&vbImpl->bindCount);
2247     }
2248     if (oldSrc != NULL) {
2249         InterlockedDecrement(&((IWineD3DVertexBufferImpl *) oldSrc)->bindCount);
2250     }
2251
2252     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2253
2254     return WINED3D_OK;
2255 }
2256
2257 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2258     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2259     UINT streamFlags;
2260
2261     TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2262            This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2263
2264
2265     streamFlags = StreamNumber &(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2266     if (streamFlags) {
2267         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2268            FIXME("stream index data not supported\n");
2269         }
2270         if (streamFlags & WINED3DSTREAMSOURCE_INDEXEDDATA) {
2271             FIXME("stream instance data not supported\n");
2272         }
2273     }
2274
2275     StreamNumber&= ~(WINED3DSTREAMSOURCE_INDEXEDDATA | WINED3DSTREAMSOURCE_INSTANCEDATA);
2276
2277     if (StreamNumber >= MAX_STREAMS) {
2278         WARN("Stream out of range %d\n", StreamNumber);
2279         return WINED3DERR_INVALIDCALL;
2280     }
2281     *pStream = This->stateBlock->streamSource[StreamNumber];
2282     *pStride = This->stateBlock->streamStride[StreamNumber];
2283     if (pOffset) {
2284         *pOffset = This->stateBlock->streamOffset[StreamNumber];
2285     }
2286
2287     if (*pStream != NULL) {
2288         IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2289     }
2290     return WINED3D_OK;
2291 }
2292
2293 /*Should be quite easy, just an extension of vertexdata
2294 ref...
2295 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
2296
2297 The divider is a bit odd though
2298
2299 VertexOffset = StartVertex / Divider * StreamStride +
2300                VertexIndex / Divider * StreamStride + StreamOffset
2301
2302 */
2303 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
2304     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2305
2306     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2307     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA  | WINED3DSTREAMSOURCE_INDEXEDDATA );
2308
2309     This->updateStateBlock->changed.streamFreq[StreamNumber]  = TRUE;
2310     This->updateStateBlock->set.streamFreq[StreamNumber]      = TRUE;
2311     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
2312
2313     if (This->updateStateBlock->streamFlags[StreamNumber] || This->updateStateBlock->streamFreq[StreamNumber] != 1) {
2314         FIXME("Stream indexing not fully supported\n");
2315     }
2316
2317     return WINED3D_OK;
2318 }
2319
2320 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
2321     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2322
2323     TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2324     *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2325
2326     TRACE("(%p) : returning %d\n", This, *Divider);
2327
2328     return WINED3D_OK;
2329 }
2330
2331 /*****
2332  * Get / Set & Multiply Transform
2333  *****/
2334 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2335     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2336
2337     /* Most of this routine, comments included copied from ddraw tree initially: */
2338     TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2339
2340     /* Handle recording of state blocks */
2341     if (This->isRecordingState) {
2342         TRACE("Recording... not performing anything\n");
2343         This->updateStateBlock->changed.transform[d3dts] = TRUE;
2344         This->updateStateBlock->set.transform[d3dts]     = TRUE;
2345         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2346         return WINED3D_OK;
2347     }
2348
2349     /*
2350      * If the new matrix is the same as the current one,
2351      * we cut off any further processing. this seems to be a reasonable
2352      * optimization because as was noticed, some apps (warcraft3 for example)
2353      * tend towards setting the same matrix repeatedly for some reason.
2354      *
2355      * From here on we assume that the new matrix is different, wherever it matters.
2356      */
2357     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2358         TRACE("The app is setting the same matrix over again\n");
2359         return WINED3D_OK;
2360     } else {
2361         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2362     }
2363
2364     /*
2365        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2366        where ViewMat = Camera space, WorldMat = world space.
2367
2368        In OpenGL, camera and world space is combined into GL_MODELVIEW
2369        matrix.  The Projection matrix stay projection matrix.
2370      */
2371
2372     /* Capture the times we can just ignore the change for now */
2373     if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2374         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2375         /* Handled by the state manager */
2376     }
2377
2378     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2379     return WINED3D_OK;
2380
2381 }
2382 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2383     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2384     TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2385     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2386     return WINED3D_OK;
2387 }
2388
2389 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2390     WINED3DMATRIX *mat = NULL;
2391     WINED3DMATRIX temp;
2392
2393     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2394      * below means it will be recorded in a state block change, but it
2395      * works regardless where it is recorded.
2396      * If this is found to be wrong, change to StateBlock.
2397      */
2398     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2399     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2400
2401     if (State < HIGHEST_TRANSFORMSTATE)
2402     {
2403         mat = &This->updateStateBlock->transforms[State];
2404     } else {
2405         FIXME("Unhandled transform state!!\n");
2406     }
2407
2408     multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2409
2410     /* Apply change via set transform - will reapply to eg. lights this way */
2411     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2412 }
2413
2414 /*****
2415  * Get / Set Light
2416  *****/
2417 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2418    you can reference any indexes you want as long as that number max are enabled at any
2419    one point in time! Therefore since the indexes can be anything, we need a linked list of them.
2420    However, this causes stateblock problems. When capturing the state block, I duplicate the list,
2421    but when recording, just build a chain pretty much of commands to be replayed.                  */
2422
2423 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2424     float rho;
2425     PLIGHTINFOEL *object, *temp;
2426
2427     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2428     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2429
2430     /* If recording state block, just add to end of lights chain */
2431     if (This->isRecordingState) {
2432         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2433         if (NULL == object) {
2434             return WINED3DERR_OUTOFVIDEOMEMORY;
2435         }
2436         memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2437         object->OriginalIndex = Index;
2438         object->glIndex = -1;
2439         object->changed = TRUE;
2440
2441         /* Add to the END of the chain of lights changes to be replayed */
2442         if (This->updateStateBlock->lights == NULL) {
2443             This->updateStateBlock->lights = object;
2444         } else {
2445             temp = This->updateStateBlock->lights;
2446             while (temp->next != NULL) temp=temp->next;
2447             temp->next = object;
2448         }
2449         TRACE("Recording... not performing anything more\n");
2450         return WINED3D_OK;
2451     }
2452
2453     /* Ok, not recording any longer so do real work */
2454     object = This->stateBlock->lights;
2455     while (object != NULL && object->OriginalIndex != Index) object = object->next;
2456
2457     /* If we didn't find it in the list of lights, time to add it */
2458     if (object == NULL) {
2459         PLIGHTINFOEL *insertAt,*prevPos;
2460
2461         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2462         if (NULL == object) {
2463             return WINED3DERR_OUTOFVIDEOMEMORY;
2464         }
2465         object->OriginalIndex = Index;
2466         object->glIndex = -1;
2467
2468         /* Add it to the front of list with the idea that lights will be changed as needed
2469            BUT after any lights currently assigned GL indexes                             */
2470         insertAt = This->stateBlock->lights;
2471         prevPos  = NULL;
2472         while (insertAt != NULL && insertAt->glIndex != -1) {
2473             prevPos  = insertAt;
2474             insertAt = insertAt->next;
2475         }
2476
2477         if (insertAt == NULL && prevPos == NULL) { /* Start of list */
2478             This->stateBlock->lights = object;
2479         } else if (insertAt == NULL) { /* End of list */
2480             prevPos->next = object;
2481             object->prev = prevPos;
2482         } else { /* Middle of chain */
2483             if (prevPos == NULL) {
2484                 This->stateBlock->lights = object;
2485             } else {
2486                 prevPos->next = object;
2487             }
2488             object->prev = prevPos;
2489             object->next = insertAt;
2490             insertAt->prev = object;
2491         }
2492     }
2493
2494     /* Initialize the object */
2495     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,
2496           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2497           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2498           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2499     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2500           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2501     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2502
2503     /* Save away the information */
2504     memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2505
2506     switch (pLight->Type) {
2507     case WINED3DLIGHT_POINT:
2508         /* Position */
2509         object->lightPosn[0] = pLight->Position.x;
2510         object->lightPosn[1] = pLight->Position.y;
2511         object->lightPosn[2] = pLight->Position.z;
2512         object->lightPosn[3] = 1.0f;
2513         object->cutoff = 180.0f;
2514         /* FIXME: Range */
2515         break;
2516
2517     case WINED3DLIGHT_DIRECTIONAL:
2518         /* Direction */
2519         object->lightPosn[0] = -pLight->Direction.x;
2520         object->lightPosn[1] = -pLight->Direction.y;
2521         object->lightPosn[2] = -pLight->Direction.z;
2522         object->lightPosn[3] = 0.0;
2523         object->exponent     = 0.0f;
2524         object->cutoff       = 180.0f;
2525         break;
2526
2527     case WINED3DLIGHT_SPOT:
2528         /* Position */
2529         object->lightPosn[0] = pLight->Position.x;
2530         object->lightPosn[1] = pLight->Position.y;
2531         object->lightPosn[2] = pLight->Position.z;
2532         object->lightPosn[3] = 1.0;
2533
2534         /* Direction */
2535         object->lightDirn[0] = pLight->Direction.x;
2536         object->lightDirn[1] = pLight->Direction.y;
2537         object->lightDirn[2] = pLight->Direction.z;
2538         object->lightDirn[3] = 1.0;
2539
2540         /*
2541          * opengl-ish and d3d-ish spot lights use too different models for the
2542          * light "intensity" as a function of the angle towards the main light direction,
2543          * so we only can approximate very roughly.
2544          * however spot lights are rather rarely used in games (if ever used at all).
2545          * furthermore if still used, probably nobody pays attention to such details.
2546          */
2547         if (pLight->Falloff == 0) {
2548             rho = 6.28f;
2549         } else {
2550             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2551         }
2552         if (rho < 0.0001) rho = 0.0001f;
2553         object->exponent = -0.3/log(cos(rho/2));
2554         if (object->exponent > 128.0) {
2555                 object->exponent = 128.0;
2556         }
2557         object->cutoff = pLight->Phi*90/M_PI;
2558
2559         /* FIXME: Range */
2560         break;
2561
2562     default:
2563         FIXME("Unrecognized light type %d\n", pLight->Type);
2564     }
2565
2566     /* Update the live definitions if the light is currently assigned a glIndex */
2567     if (object->glIndex != -1) {
2568         setup_light(iface, object->glIndex, object);
2569     }
2570     return WINED3D_OK;
2571 }
2572
2573 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2574     PLIGHTINFOEL *lightInfo = NULL;
2575     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2576     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2577
2578     /* Locate the light in the live lights */
2579     lightInfo = This->stateBlock->lights;
2580     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2581
2582     if (lightInfo == NULL) {
2583         TRACE("Light information requested but light not defined\n");
2584         return WINED3DERR_INVALIDCALL;
2585     }
2586
2587     memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2588     return WINED3D_OK;
2589 }
2590
2591 /*****
2592  * Get / Set Light Enable
2593  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2594  *****/
2595 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2596     PLIGHTINFOEL *lightInfo = NULL;
2597     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2598     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2599
2600     /* Tests show true = 128...not clear why */
2601
2602     Enable = Enable? 128: 0;
2603
2604     /* If recording state block, just add to end of lights chain with changedEnable set to true */
2605     if (This->isRecordingState) {
2606         lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
2607         if (NULL == lightInfo) {
2608             return WINED3DERR_OUTOFVIDEOMEMORY;
2609         }
2610         lightInfo->OriginalIndex = Index;
2611         lightInfo->glIndex = -1;
2612         lightInfo->enabledChanged = TRUE;
2613         lightInfo->lightEnabled = Enable;
2614
2615         /* Add to the END of the chain of lights changes to be replayed */
2616         if (This->updateStateBlock->lights == NULL) {
2617             This->updateStateBlock->lights = lightInfo;
2618         } else {
2619             PLIGHTINFOEL *temp = This->updateStateBlock->lights;
2620             while (temp->next != NULL) temp=temp->next;
2621             temp->next = lightInfo;
2622         }
2623         TRACE("Recording... not performing anything more\n");
2624         return WINED3D_OK;
2625     }
2626
2627     /* Not recording... So, locate the light in the live lights */
2628     lightInfo = This->stateBlock->lights;
2629     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2630
2631     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2632     if (lightInfo == NULL) {
2633
2634         TRACE("Light enabled requested but light not defined, so defining one!\n");
2635         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2636
2637         /* Search for it again! Should be fairly quick as near head of list */
2638         lightInfo = This->stateBlock->lights;
2639         while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2640         if (lightInfo == NULL) {
2641             FIXME("Adding default lights has failed dismally\n");
2642             return WINED3DERR_INVALIDCALL;
2643         }
2644     }
2645
2646     /* OK, we now have a light... */
2647     if (!Enable) {
2648
2649         /* If we are disabling it, check it was enabled, and
2650            still only do something if it has assigned a glIndex (which it should have!)   */
2651         if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2652             TRACE("Disabling light set up at gl idx %d\n", lightInfo->glIndex);
2653             ENTER_GL();
2654             glDisable(GL_LIGHT0 + lightInfo->glIndex);
2655             checkGLcall("glDisable GL_LIGHT0+Index");
2656             LEAVE_GL();
2657         } else {
2658             TRACE("Nothing to do as light was not enabled\n");
2659         }
2660         lightInfo->lightEnabled = Enable;
2661     } else {
2662
2663         /* We are enabling it. If it is enabled, it's really simple */
2664         if (lightInfo->lightEnabled) {
2665             /* nop */
2666             TRACE("Nothing to do as light was enabled\n");
2667
2668         /* If it already has a glIndex, it's still simple */
2669         } else if (lightInfo->glIndex != -1) {
2670             TRACE("Reusing light as already set up at gl idx %d\n", lightInfo->glIndex);
2671             lightInfo->lightEnabled = Enable;
2672             ENTER_GL();
2673             glEnable(GL_LIGHT0 + lightInfo->glIndex);
2674             checkGLcall("glEnable GL_LIGHT0+Index already setup");
2675             LEAVE_GL();
2676
2677         /* Otherwise got to find space - lights are ordered gl indexes first */
2678         } else {
2679             PLIGHTINFOEL *bsf  = NULL;
2680             PLIGHTINFOEL *pos  = This->stateBlock->lights;
2681             PLIGHTINFOEL *prev = NULL;
2682             int           Index= 0;
2683             int           glIndex = -1;
2684
2685             /* Try to minimize changes as much as possible */
2686             while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2687
2688                 /* Try to remember which index can be replaced if necessary */
2689                 if (bsf==NULL && !pos->lightEnabled) {
2690                     /* Found a light we can replace, save as best replacement */
2691                     bsf = pos;
2692                 }
2693
2694                 /* Step to next space */
2695                 prev = pos;
2696                 pos = pos->next;
2697                 Index ++;
2698             }
2699
2700             /* If we have too many active lights, fail the call */
2701             if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2702                 FIXME("Program requests too many concurrent lights\n");
2703                 return WINED3DERR_INVALIDCALL;
2704
2705             /* If we have allocated all lights, but not all are enabled,
2706                reuse one which is not enabled                           */
2707             } else if (Index == This->maxConcurrentLights) {
2708                 /* use bsf - Simply swap the new light and the BSF one */
2709                 PLIGHTINFOEL *bsfNext = bsf->next;
2710                 PLIGHTINFOEL *bsfPrev = bsf->prev;
2711
2712                 /* Sort out ends */
2713                 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2714                 if (bsf->prev != NULL) {
2715                     bsf->prev->next = lightInfo;
2716                 } else {
2717                     This->stateBlock->lights = lightInfo;
2718                 }
2719
2720                 /* If not side by side, lots of chains to update */
2721                 if (bsf->next != lightInfo) {
2722                     lightInfo->prev->next = bsf;
2723                     bsf->next->prev = lightInfo;
2724                     bsf->next       = lightInfo->next;
2725                     bsf->prev       = lightInfo->prev;
2726                     lightInfo->next = bsfNext;
2727                     lightInfo->prev = bsfPrev;
2728
2729                 } else {
2730                     /* Simple swaps */
2731                     bsf->prev = lightInfo;
2732                     bsf->next = lightInfo->next;
2733                     lightInfo->next = bsf;
2734                     lightInfo->prev = bsfPrev;
2735                 }
2736
2737
2738                 /* Update states */
2739                 glIndex = bsf->glIndex;
2740                 bsf->glIndex = -1;
2741                 lightInfo->glIndex = glIndex;
2742                 lightInfo->lightEnabled = Enable;
2743
2744                 /* Finally set up the light in gl itself */
2745                 TRACE("Replacing light which was set up at gl idx %d\n", lightInfo->glIndex);
2746                 ENTER_GL();
2747                 setup_light(iface, glIndex, lightInfo);
2748                 glEnable(GL_LIGHT0 + glIndex);
2749                 checkGLcall("glEnable GL_LIGHT0 new setup");
2750                 LEAVE_GL();
2751
2752             /* If we reached the end of the allocated lights, with space in the
2753                gl lights, setup a new light                                     */
2754             } else if (pos->glIndex == -1) {
2755
2756                 /* We reached the end of the allocated gl lights, so already
2757                     know the index of the next one!                          */
2758                 glIndex = Index;
2759                 lightInfo->glIndex = glIndex;
2760                 lightInfo->lightEnabled = Enable;
2761
2762                 /* In an ideal world, it's already in the right place */
2763                 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2764                    /* No need to move it */
2765                 } else {
2766                     /* Remove this light from the list */
2767                     lightInfo->prev->next = lightInfo->next;
2768                     if (lightInfo->next != NULL) {
2769                         lightInfo->next->prev = lightInfo->prev;
2770                     }
2771
2772                     /* Add in at appropriate place (inbetween prev and pos) */
2773                     lightInfo->prev = prev;
2774                     lightInfo->next = pos;
2775                     if (prev == NULL) {
2776                         This->stateBlock->lights = lightInfo;
2777                     } else {
2778                         prev->next = lightInfo;
2779                     }
2780                     if (pos != NULL) {
2781                         pos->prev = lightInfo;
2782                     }
2783                 }
2784
2785                 /* Finally set up the light in gl itself */
2786                 TRACE("Defining new light at gl idx %d\n", lightInfo->glIndex);
2787                 ENTER_GL();
2788                 setup_light(iface, glIndex, lightInfo);
2789                 glEnable(GL_LIGHT0 + glIndex);
2790                 checkGLcall("glEnable GL_LIGHT0 new setup");
2791                 LEAVE_GL();
2792
2793             }
2794         }
2795     }
2796     return WINED3D_OK;
2797 }
2798
2799 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2800
2801     PLIGHTINFOEL *lightInfo = NULL;
2802     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2803     TRACE("(%p) : for idx(%d)\n", This, Index);
2804
2805     /* Locate the light in the live lights */
2806     lightInfo = This->stateBlock->lights;
2807     while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2808
2809     if (lightInfo == NULL) {
2810         TRACE("Light enabled state requested but light not defined\n");
2811         return WINED3DERR_INVALIDCALL;
2812     }
2813     *pEnable = lightInfo->lightEnabled;
2814     return WINED3D_OK;
2815 }
2816
2817 /*****
2818  * Get / Set Clip Planes
2819  *****/
2820 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2821     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2822     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
2823
2824     /* Validate Index */
2825     if (Index >= GL_LIMITS(clipplanes)) {
2826         TRACE("Application has requested clipplane this device doesn't support\n");
2827         return WINED3DERR_INVALIDCALL;
2828     }
2829
2830     This->updateStateBlock->changed.clipplane[Index] = TRUE;
2831     This->updateStateBlock->set.clipplane[Index] = TRUE;
2832     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2833     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2834     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2835     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2836
2837     /* Handle recording of state blocks */
2838     if (This->isRecordingState) {
2839         TRACE("Recording... not performing anything\n");
2840         return WINED3D_OK;
2841     }
2842
2843     /* Apply it */
2844
2845     ENTER_GL();
2846
2847     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2848     glMatrixMode(GL_MODELVIEW);
2849     glPushMatrix();
2850     glLoadMatrixf((float *) &This->stateBlock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2851
2852     TRACE("Clipplane [%f,%f,%f,%f]\n",
2853           This->updateStateBlock->clipplane[Index][0],
2854           This->updateStateBlock->clipplane[Index][1],
2855           This->updateStateBlock->clipplane[Index][2],
2856           This->updateStateBlock->clipplane[Index][3]);
2857     glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2858     checkGLcall("glClipPlane");
2859
2860     glPopMatrix();
2861     LEAVE_GL();
2862
2863     return WINED3D_OK;
2864 }
2865
2866 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2867     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2868     TRACE("(%p) : for idx %d\n", This, Index);
2869
2870     /* Validate Index */
2871     if (Index >= GL_LIMITS(clipplanes)) {
2872         TRACE("Application has requested clipplane this device doesn't support\n");
2873         return WINED3DERR_INVALIDCALL;
2874     }
2875
2876     pPlane[0] = This->stateBlock->clipplane[Index][0];
2877     pPlane[1] = This->stateBlock->clipplane[Index][1];
2878     pPlane[2] = This->stateBlock->clipplane[Index][2];
2879     pPlane[3] = This->stateBlock->clipplane[Index][3];
2880     return WINED3D_OK;
2881 }
2882
2883 /*****
2884  * Get / Set Clip Plane Status
2885  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2886  *****/
2887 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2888     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2889     FIXME("(%p) : stub\n", This);
2890     if (NULL == pClipStatus) {
2891       return WINED3DERR_INVALIDCALL;
2892     }
2893     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2894     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2895     return WINED3D_OK;
2896 }
2897
2898 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2899     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2900     FIXME("(%p) : stub\n", This);
2901     if (NULL == pClipStatus) {
2902       return WINED3DERR_INVALIDCALL;
2903     }
2904     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2905     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2906     return WINED3D_OK;
2907 }
2908
2909 /*****
2910  * Get / Set Material
2911  *****/
2912 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2913     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2914
2915     This->updateStateBlock->changed.material = TRUE;
2916     This->updateStateBlock->set.material = TRUE;
2917     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2918
2919     /* Handle recording of state blocks */
2920     if (This->isRecordingState) {
2921         TRACE("Recording... not performing anything\n");
2922         return WINED3D_OK;
2923     }
2924
2925     ENTER_GL();
2926     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2927         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2928     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2929         pMaterial->Ambient.b, pMaterial->Ambient.a);
2930     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2931         pMaterial->Specular.b, pMaterial->Specular.a);
2932     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2933         pMaterial->Emissive.b, pMaterial->Emissive.a);
2934     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2935
2936     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2937     checkGLcall("glMaterialfv(GL_AMBIENT)");
2938     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2939     checkGLcall("glMaterialfv(GL_DIFFUSE)");
2940
2941     /* Only change material color if specular is enabled, otherwise it is set to black */
2942     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2943        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2944        checkGLcall("glMaterialfv(GL_SPECULAR");
2945     } else {
2946        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2947        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2948        checkGLcall("glMaterialfv(GL_SPECULAR");
2949     }
2950     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2951     checkGLcall("glMaterialfv(GL_EMISSION)");
2952     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2953     checkGLcall("glMaterialf(GL_SHININESS");
2954
2955     LEAVE_GL();
2956     return WINED3D_OK;
2957 }
2958
2959 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2960     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2961     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2962     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2963         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2964     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2965         pMaterial->Ambient.b, pMaterial->Ambient.a);
2966     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2967         pMaterial->Specular.b, pMaterial->Specular.a);
2968     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2969         pMaterial->Emissive.b, pMaterial->Emissive.a);
2970     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2971
2972     return WINED3D_OK;
2973 }
2974
2975 /*****
2976  * Get / Set Indices
2977  *****/
2978 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2979                                              UINT BaseVertexIndex) {
2980     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
2981     IWineD3DIndexBuffer *oldIdxs;
2982     UINT oldBaseIndex = This->updateStateBlock->baseVertexIndex;
2983
2984     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2985     oldIdxs = This->updateStateBlock->pIndexData;
2986
2987     This->updateStateBlock->changed.indices = TRUE;
2988     This->updateStateBlock->set.indices = TRUE;
2989     This->updateStateBlock->pIndexData = pIndexData;
2990     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2991
2992     /* Handle recording of state blocks */
2993     if (This->isRecordingState) {
2994         TRACE("Recording... not performing anything\n");
2995         return WINED3D_OK;
2996     }
2997
2998     /* So far only the base vertex index is tracked */
2999     if(BaseVertexIndex != oldBaseIndex) {
3000         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
3001     }
3002     return WINED3D_OK;
3003 }
3004
3005 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
3006     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3007
3008     *ppIndexData = This->stateBlock->pIndexData;
3009
3010     /* up ref count on ppindexdata */
3011     if (*ppIndexData) {
3012         IWineD3DIndexBuffer_AddRef(*ppIndexData);
3013         *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
3014         TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
3015     }else{
3016         TRACE("(%p) No index data set\n", This);
3017     }
3018     TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
3019
3020     return WINED3D_OK;
3021 }
3022
3023 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
3024 static HRESULT WINAPI IWineD3DDeviceImpl_SetBasevertexIndex(IWineD3DDevice *iface, UINT BaseIndex) {
3025     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3026     TRACE("(%p)->(%d)\n", This, BaseIndex);
3027
3028     if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
3029         TRACE("Application is setting the old value over, nothing to do\n");
3030         return WINED3D_OK;
3031     }
3032
3033     This->updateStateBlock->baseVertexIndex = BaseIndex;
3034
3035     if (This->isRecordingState) {
3036         TRACE("Recording... not performing anything\n");
3037         return WINED3D_OK;
3038     }
3039     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
3040     return WINED3D_OK;
3041 }
3042
3043 /*****
3044  * Get / Set Viewports
3045  *****/
3046 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
3047     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3048
3049     TRACE("(%p)\n", This);
3050     This->updateStateBlock->changed.viewport = TRUE;
3051     This->updateStateBlock->set.viewport = TRUE;
3052     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
3053
3054     /* Handle recording of state blocks */
3055     if (This->isRecordingState) {
3056         TRACE("Recording... not performing anything\n");
3057         return WINED3D_OK;
3058     }
3059
3060     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
3061           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
3062
3063     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
3064     return WINED3D_OK;
3065
3066 }
3067
3068 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
3069     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3070     TRACE("(%p)\n", This);
3071     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
3072     return WINED3D_OK;
3073 }
3074
3075 /*****
3076  * Get / Set Render States
3077  * TODO: Verify against dx9 definitions
3078  *****/
3079 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
3080
3081     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
3082     DWORD oldValue = This->stateBlock->renderState[State];
3083
3084     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
3085
3086     This->updateStateBlock->changed.renderState[State] = TRUE;
3087     This->updateStateBlock->set.renderState[State] = TRUE;
3088     This->updateStateBlock->renderState[State] = Value;
3089
3090     /* Handle recording of state blocks */
3091     if (This->isRecordingState) {
3092         TRACE("Recording... not performing anything\n");
3093         return WINED3D_OK;
3094     }
3095
3096     /* Compared here and not before the assignment to allow proper stateblock recording */
3097     if(Value == oldValue) {
3098         TRACE("Application is setting the old value over, nothing to do\n");
3099     } else {
3100         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
3101     }
3102
3103     return WINED3D_OK;
3104 }
3105
3106 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
3107     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3108     TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
3109     *pValue = This->stateBlock->renderState[State];
3110     return WINED3D_OK;
3111 }
3112
3113 /*****
3114  * Get / Set Sampler States
3115  * TODO: Verify against dx9 definitions
3116  *****/
3117
3118 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3119     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3120     DWORD oldValue = This->stateBlock->samplerState[Sampler][Type];
3121
3122     /**
3123     * SetSampler is designed to allow for more than the standard up to 8 textures
3124     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
3125     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3126     *
3127     * http://developer.nvidia.com/object/General_FAQ.html#t6
3128     *
3129     * There are two new settings for GForce
3130     * the sampler one:
3131     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3132     * and the texture one:
3133     * GL_MAX_TEXTURE_COORDS_ARB.
3134     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3135      ******************/
3136     /** NOTE: States are applied in IWineD3DBaseTextre ApplyStateChanges the sampler state handler**/
3137     if(Sampler >  GL_LIMITS(sampler_stages) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3138          FIXME("sampler %d type %s(%u) is out of range [max_samplers=%d, highest_state=%d]\n",
3139             Sampler, debug_d3dsamplerstate(Type), Type, GL_LIMITS(sampler_stages), WINED3D_HIGHEST_SAMPLER_STATE);
3140         return WINED3DERR_INVALIDCALL;
3141     }
3142
3143     TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
3144         debug_d3dsamplerstate(Type), Type, Value);
3145     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
3146     This->updateStateBlock->set.samplerState[Sampler][Type]     = Value;
3147     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
3148
3149     /* Handle recording of state blocks */
3150     if (This->isRecordingState) {
3151         TRACE("Recording... not performing anything\n");
3152         return WINED3D_OK;
3153     }
3154
3155     if(oldValue == Value) {
3156         TRACE("Application is setting the old value over, nothing to do\n");
3157         return WINED3D_OK;
3158     }
3159
3160     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
3161
3162     return WINED3D_OK;
3163 }
3164
3165 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3166     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3167     /** TODO: check that sampler is in  range **/
3168     *Value = This->stateBlock->samplerState[Sampler][Type];
3169     TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
3170
3171     return WINED3D_OK;
3172 }
3173
3174 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3175     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3176     RECT windowRect;
3177     UINT winHeight;
3178
3179     This->updateStateBlock->set.scissorRect = TRUE;
3180     This->updateStateBlock->changed.scissorRect = TRUE;
3181     memcpy(&This->updateStateBlock->scissorRect, pRect, sizeof(*pRect));
3182
3183     if(This->isRecordingState) {
3184         TRACE("Recording... not performing anything\n");
3185         return WINED3D_OK;
3186     }
3187
3188     GetClientRect(((IWineD3DSwapChainImpl *)This->swapchains[0])->win_handle, &windowRect);
3189     /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3190     * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3191     */
3192     winHeight = windowRect.bottom - windowRect.top;
3193     TRACE("(%p)Setting new Scissor Rect to %d:%d-%d:%d\n", This, pRect->left, pRect->bottom - winHeight,
3194           pRect->right - pRect->left, pRect->bottom - pRect->top);
3195     ENTER_GL();
3196     glScissor(pRect->left, winHeight - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3197     checkGLcall("glScissor");
3198     LEAVE_GL();
3199
3200     return WINED3D_OK;
3201 }
3202
3203 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3204     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3205
3206     memcpy(pRect, &This->updateStateBlock->scissorRect, sizeof(pRect));
3207     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3208     return WINED3D_OK;
3209 }
3210
3211 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3212     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3213     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
3214
3215     TRACE("(%p) : pDecl=%p\n", This, pDecl);
3216
3217     This->updateStateBlock->vertexDecl = pDecl;
3218     This->updateStateBlock->changed.vertexDecl = TRUE;
3219     This->updateStateBlock->set.vertexDecl = TRUE;
3220
3221     if (This->isRecordingState) {
3222         TRACE("Recording... not performing anything\n");
3223         return WINED3D_OK;
3224     } else if(pDecl == oldDecl) {
3225         /* Checked after the assignment to allow proper stateblock recording */
3226         TRACE("Application is setting the old declaration over, nothing to do\n");
3227         return WINED3D_OK;
3228     }
3229
3230     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
3231     return WINED3D_OK;
3232 }
3233
3234 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3235     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3236
3237     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3238
3239     *ppDecl = This->stateBlock->vertexDecl;
3240     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3241     return WINED3D_OK;
3242 }
3243
3244 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3245     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3246     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
3247
3248     This->updateStateBlock->vertexShader         = pShader;
3249     This->updateStateBlock->changed.vertexShader = TRUE;
3250     This->updateStateBlock->set.vertexShader     = TRUE;
3251
3252     if (This->isRecordingState) {
3253         TRACE("Recording... not performing anything\n");
3254         return WINED3D_OK;
3255     } else if(oldShader == pShader) {
3256         /* Checked here to allow proper stateblock recording */
3257         TRACE("App is setting the old shader over, nothing to do\n");
3258         return WINED3D_OK;
3259     }
3260
3261     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3262
3263     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
3264
3265     return WINED3D_OK;
3266 }
3267
3268 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3269     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3270
3271     if (NULL == ppShader) {
3272         return WINED3DERR_INVALIDCALL;
3273     }
3274     *ppShader = This->stateBlock->vertexShader;
3275     if( NULL != *ppShader)
3276         IWineD3DVertexShader_AddRef(*ppShader);
3277
3278     TRACE("(%p) : returning %p\n", This, *ppShader);
3279     return WINED3D_OK;
3280 }
3281
3282 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
3283     IWineD3DDevice *iface,
3284     UINT start,
3285     CONST BOOL *srcData,
3286     UINT count) {
3287
3288     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3289     int i, cnt = min(count, MAX_CONST_B - start);
3290
3291     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3292             iface, srcData, start, count);
3293
3294     if (srcData == NULL || cnt < 0)
3295         return WINED3DERR_INVALIDCALL;
3296
3297     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3298     for (i = 0; i < cnt; i++)
3299         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3300
3301     for (i = start; i < cnt + start; ++i) {
3302         This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
3303         This->updateStateBlock->set.vertexShaderConstantsB[i]     = TRUE;
3304     }
3305
3306     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3307
3308     return WINED3D_OK;
3309 }
3310
3311 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
3312     IWineD3DDevice *iface,
3313     UINT start,
3314     BOOL *dstData,
3315     UINT count) {
3316
3317     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3318     int cnt = min(count, MAX_CONST_B - start);
3319
3320     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3321             iface, dstData, start, count);
3322
3323     if (dstData == NULL || cnt < 0)
3324         return WINED3DERR_INVALIDCALL;
3325
3326     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
3327     return WINED3D_OK;
3328 }
3329
3330 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
3331     IWineD3DDevice *iface,
3332     UINT start,
3333     CONST int *srcData,
3334     UINT count) {
3335
3336     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3337     int i, cnt = min(count, MAX_CONST_I - start);
3338
3339     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3340             iface, srcData, start, count);
3341
3342     if (srcData == NULL || cnt < 0)
3343         return WINED3DERR_INVALIDCALL;
3344
3345     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3346     for (i = 0; i < cnt; i++)
3347         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3348            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3349
3350     for (i = start; i < cnt + start; ++i) {
3351         This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
3352         This->updateStateBlock->set.vertexShaderConstantsI[i]     = TRUE;
3353     }
3354
3355     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3356
3357     return WINED3D_OK;
3358 }
3359
3360 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
3361     IWineD3DDevice *iface,
3362     UINT start,
3363     int *dstData,
3364     UINT count) {
3365
3366     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3367     int cnt = min(count, MAX_CONST_I - start);
3368
3369     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3370             iface, dstData, start, count);
3371
3372     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
3373         return WINED3DERR_INVALIDCALL;
3374
3375     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3376     return WINED3D_OK;
3377 }
3378
3379 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
3380     IWineD3DDevice *iface,
3381     UINT start,
3382     CONST float *srcData,
3383     UINT count) {
3384
3385     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3386     int i, cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3387
3388     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3389             iface, srcData, start, count);
3390
3391     if (srcData == NULL || ((signed int) GL_LIMITS(vshader_constantsF) - (signed int) start) <= (signed int) 0)
3392         return WINED3DERR_INVALIDCALL;
3393
3394     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
3395     for (i = 0; i < cnt; i++)
3396         TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3397            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3398
3399     for (i = start; i < cnt + start; ++i) {
3400         if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
3401             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
3402             ptr->idx = i;
3403             list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
3404             This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
3405         }
3406         This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
3407     }
3408
3409     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3410
3411     return WINED3D_OK;
3412 }
3413
3414 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3415     IWineD3DDevice *iface,
3416     UINT start,
3417     float *dstData,
3418     UINT count) {
3419
3420     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3421     int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3422
3423     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3424             iface, dstData, start, count);
3425
3426     if (dstData == NULL || cnt < 0)
3427         return WINED3DERR_INVALIDCALL;
3428
3429     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3430     return WINED3D_OK;
3431 }
3432
3433 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3434     DWORD i;
3435     for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
3436         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3437     }
3438 }
3439
3440 static void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3441     DWORD i, tex;
3442     /* This code can assume that GL_NV_register_combiners are supported, otherwise
3443      * it is never called.
3444      *
3445      * Rules are:
3446      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3447      * that would be really messy and require shader recompilation
3448      * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3449      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3450      * -> Whith a 1:1 mapping oneToOneTexUnitMap is set to avoid checking MAX_SAMPLERS array
3451      * entries to make pixel shaders cheaper. MAX_SAMPLERS will be 128 in dx10
3452      */
3453     if(This->stateBlock->pixelShader || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) {
3454         if(This->oneToOneTexUnitMap) {
3455             TRACE("Not touching 1:1 map\n");
3456             return;
3457         }
3458         TRACE("Restoring 1:1 texture unit mapping\n");
3459         /* Restore a 1:1 mapping */
3460         for(i = 0; i < MAX_SAMPLERS; i++) {
3461             if(This->texUnitMap[i] != i) {
3462                 This->texUnitMap[i] = i;
3463                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3464                 markTextureStagesDirty(This, i);
3465             }
3466         }
3467         This->oneToOneTexUnitMap = TRUE;
3468         return;
3469     } else {
3470         /* No pixel shader, and we do not have enough texture units available. Try to skip NULL textures
3471          * First, see if we can succeed at all
3472          */
3473         tex = 0;
3474         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3475             if(This->stateBlock->textures[i] == NULL) tex++;
3476         }
3477
3478         if(GL_LIMITS(textures) + tex < This->stateBlock->lowest_disabled_stage) {
3479             FIXME("Too many bound textures to support the combiner settings\n");
3480             return;
3481         }
3482
3483         /* Now work out the mapping */
3484         tex = 0;
3485         This->oneToOneTexUnitMap = FALSE;
3486         WARN("Non 1:1 mapping UNTESTED!\n");
3487         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3488             /* Skip NULL textures */
3489             if (!This->stateBlock->textures[i]) {
3490                 /* Map to -1, so the check below doesn't fail if a non-NULL
3491                  * texture is set on this stage */
3492                 TRACE("Mapping texture stage %d to -1\n", i);
3493                 This->texUnitMap[i] = -1;
3494
3495                 continue;
3496             }
3497
3498             TRACE("Mapping texture stage %d to unit %d\n", i, tex);
3499             if(This->texUnitMap[i] != tex) {
3500                 This->texUnitMap[i] = tex;
3501                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3502                 markTextureStagesDirty(This, i);
3503             }
3504
3505             ++tex;
3506         }
3507     }
3508 }
3509
3510 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3511     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3512     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3513     This->updateStateBlock->pixelShader         = pShader;
3514     This->updateStateBlock->changed.pixelShader = TRUE;
3515     This->updateStateBlock->set.pixelShader     = TRUE;
3516
3517     /* Handle recording of state blocks */
3518     if (This->isRecordingState) {
3519         TRACE("Recording... not performing anything\n");
3520     }
3521
3522     if (This->isRecordingState) {
3523         TRACE("Recording... not performing anything\n");
3524         return WINED3D_OK;
3525     }
3526
3527     if(pShader == oldShader) {
3528         TRACE("App is setting the old pixel shader over, nothing to do\n");
3529         return WINED3D_OK;
3530     }
3531
3532     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3533     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3534
3535     /* Rebuild the texture unit mapping if nvrc's are supported */
3536     if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3537         IWineD3DDeviceImpl_FindTexUnitMap(This);
3538     }
3539
3540     return WINED3D_OK;
3541 }
3542
3543 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3544     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3545
3546     if (NULL == ppShader) {
3547         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3548         return WINED3DERR_INVALIDCALL;
3549     }
3550
3551     *ppShader =  This->stateBlock->pixelShader;
3552     if (NULL != *ppShader) {
3553         IWineD3DPixelShader_AddRef(*ppShader);
3554     }
3555     TRACE("(%p) : returning %p\n", This, *ppShader);
3556     return WINED3D_OK;
3557 }
3558
3559 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3560     IWineD3DDevice *iface,
3561     UINT start,
3562     CONST BOOL *srcData,
3563     UINT count) {
3564
3565     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3566     int i, cnt = min(count, MAX_CONST_B - start);
3567
3568     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3569             iface, srcData, start, count);
3570
3571     if (srcData == NULL || cnt < 0)
3572         return WINED3DERR_INVALIDCALL;
3573
3574     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3575     for (i = 0; i < cnt; i++)
3576         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3577
3578     for (i = start; i < cnt + start; ++i) {
3579         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3580         This->updateStateBlock->set.pixelShaderConstantsB[i]     = TRUE;
3581     }
3582
3583     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3584
3585     return WINED3D_OK;
3586 }
3587
3588 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3589     IWineD3DDevice *iface,
3590     UINT start,
3591     BOOL *dstData,
3592     UINT count) {
3593
3594     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3595     int cnt = min(count, MAX_CONST_B - start);
3596
3597     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3598             iface, dstData, start, count);
3599
3600     if (dstData == NULL || cnt < 0)
3601         return WINED3DERR_INVALIDCALL;
3602
3603     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3604     return WINED3D_OK;
3605 }
3606
3607 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3608     IWineD3DDevice *iface,
3609     UINT start,
3610     CONST int *srcData,
3611     UINT count) {
3612
3613     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3614     int i, cnt = min(count, MAX_CONST_I - start);
3615
3616     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3617             iface, srcData, start, count);
3618
3619     if (srcData == NULL || cnt < 0)
3620         return WINED3DERR_INVALIDCALL;
3621
3622     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3623     for (i = 0; i < cnt; i++)
3624         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3625            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3626
3627     for (i = start; i < cnt + start; ++i) {
3628         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3629         This->updateStateBlock->set.pixelShaderConstantsI[i]     = TRUE;
3630     }
3631
3632     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3633
3634     return WINED3D_OK;
3635 }
3636
3637 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3638     IWineD3DDevice *iface,
3639     UINT start,
3640     int *dstData,
3641     UINT count) {
3642
3643     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3644     int cnt = min(count, MAX_CONST_I - start);
3645
3646     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3647             iface, dstData, start, count);
3648
3649     if (dstData == NULL || cnt < 0)
3650         return WINED3DERR_INVALIDCALL;
3651
3652     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3653     return WINED3D_OK;
3654 }
3655
3656 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3657     IWineD3DDevice *iface,
3658     UINT start,
3659     CONST float *srcData,
3660     UINT count) {
3661
3662     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3663     int i, cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3664
3665     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3666             iface, srcData, start, count);
3667
3668     if (srcData == NULL || cnt < 0)
3669         return WINED3DERR_INVALIDCALL;
3670
3671     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, cnt * sizeof(float) * 4);
3672     for (i = 0; i < cnt; i++)
3673         TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3674            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3675
3676     for (i = start; i < cnt + start; ++i) {
3677         if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3678             constant_entry *ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(constant_entry));
3679             ptr->idx = i;
3680             list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3681             This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3682         }
3683         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3684     }
3685
3686     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3687
3688     return WINED3D_OK;
3689 }
3690
3691 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3692     IWineD3DDevice *iface,
3693     UINT start,
3694     float *dstData,
3695     UINT count) {
3696
3697     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3698     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3699
3700     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3701             iface, dstData, start, count);
3702
3703     if (dstData == NULL || cnt < 0)
3704         return WINED3DERR_INVALIDCALL;
3705
3706     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3707     return WINED3D_OK;
3708 }
3709
3710 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3711 static HRESULT
3712 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3713     char *dest_ptr, *dest_conv = NULL;
3714     unsigned int i;
3715     DWORD DestFVF = dest->fvf;
3716     WINED3DVIEWPORT vp;
3717     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3718     BOOL doClip;
3719     int numTextures;
3720
3721     if (SrcFVF & WINED3DFVF_NORMAL) {
3722         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3723     }
3724
3725     if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
3726         ERR("Source has no position mask\n");
3727         return WINED3DERR_INVALIDCALL;
3728     }
3729
3730     /* We might access VBOs from this code, so hold the lock */
3731     ENTER_GL();
3732
3733     if (dest->resource.allocatedMemory == NULL) {
3734         /* This may happen if we do direct locking into a vbo. Unlikely,
3735          * but theoretically possible(ddraw processvertices test)
3736          */
3737         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3738         if(!dest->resource.allocatedMemory) {
3739             LEAVE_GL();
3740             ERR("Out of memory\n");
3741             return E_OUTOFMEMORY;
3742         }
3743         if(dest->vbo) {
3744             void *src;
3745             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3746             checkGLcall("glBindBufferARB");
3747             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3748             if(src) {
3749                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3750             }
3751             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3752             checkGLcall("glUnmapBufferARB");
3753         }
3754     }
3755
3756     /* Get a pointer into the destination vbo(create one if none exists) and
3757      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3758      */
3759     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3760         CreateVBO(dest);
3761     }
3762
3763     if(dest->vbo) {
3764         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3765         dest_conv = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB));
3766         if(!dest_conv) {
3767             ERR("glMapBuffer failed\n");
3768             /* Continue without storing converted vertices */
3769         }
3770     }
3771
3772     /* Should I clip?
3773      * a) WINED3DRS_CLIPPING is enabled
3774      * b) WINED3DVOP_CLIP is passed
3775      */
3776     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3777         static BOOL warned = FALSE;
3778         /*
3779          * The clipping code is not quite correct. Some things need
3780          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3781          * so disable clipping for now.
3782          * (The graphics in Half-Life are broken, and my processvertices
3783          *  test crashes with IDirect3DDevice3)
3784         doClip = TRUE;
3785          */
3786         doClip = FALSE;
3787         if(!warned) {
3788            warned = TRUE;
3789            FIXME("Clipping is broken and disabled for now\n");
3790         }
3791     } else doClip = FALSE;
3792     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3793     if(dest_conv) {
3794         dest_conv = ((char *) dest_conv) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3795     }
3796
3797     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3798                                  WINED3DTS_VIEW,
3799                                  &view_mat);
3800     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3801                                  WINED3DTS_PROJECTION,
3802                                  &proj_mat);
3803     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3804                                  WINED3DTS_WORLDMATRIX(0),
3805                                  &world_mat);
3806
3807     TRACE("View mat:\n");
3808     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);
3809     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);
3810     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);
3811     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);
3812
3813     TRACE("Proj mat:\n");
3814     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);
3815     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);
3816     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);
3817     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);
3818
3819     TRACE("World mat:\n");
3820     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);
3821     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);
3822     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);
3823     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);
3824
3825     /* Get the viewport */
3826     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3827     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3828           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3829
3830     multiply_matrix(&mat,&view_mat,&world_mat);
3831     multiply_matrix(&mat,&proj_mat,&mat);
3832
3833     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3834
3835     for (i = 0; i < dwCount; i+= 1) {
3836         unsigned int tex_index;
3837
3838         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3839              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3840             /* The position first */
3841             float *p =
3842               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
3843             float x, y, z, rhw;
3844             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3845
3846             /* Multiplication with world, view and projection matrix */
3847             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);
3848             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);
3849             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);
3850             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);
3851
3852             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3853
3854             /* WARNING: The following things are taken from d3d7 and were not yet checked
3855              * against d3d8 or d3d9!
3856              */
3857
3858             /* Clipping conditions: From
3859              * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
3860              *
3861              * A vertex is clipped if it does not match the following requirements
3862              * -rhw < x <= rhw
3863              * -rhw < y <= rhw
3864              *    0 < z <= rhw
3865              *    0 < rhw ( Not in d3d7, but tested in d3d7)
3866              *
3867              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3868              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3869              *
3870              */
3871
3872             if( !doClip ||
3873                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3874                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
3875                   ( rhw > eps ) ) ) {
3876
3877                 /* "Normal" viewport transformation (not clipped)
3878                  * 1) The values are divided by rhw
3879                  * 2) The y axis is negative, so multiply it with -1
3880                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3881                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3882                  * 4) Multiply x with Width/2 and add Width/2
3883                  * 5) The same for the height
3884                  * 6) Add the viewpoint X and Y to the 2D coordinates and
3885                  *    The minimum Z value to z
3886                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3887                  *
3888                  * Well, basically it's simply a linear transformation into viewport
3889                  * coordinates
3890                  */
3891
3892                 x /= rhw;
3893                 y /= rhw;
3894                 z /= rhw;
3895
3896                 y *= -1;
3897
3898                 x *= vp.Width / 2;
3899                 y *= vp.Height / 2;
3900                 z *= vp.MaxZ - vp.MinZ;
3901
3902                 x += vp.Width / 2 + vp.X;
3903                 y += vp.Height / 2 + vp.Y;
3904                 z += vp.MinZ;
3905
3906                 rhw = 1 / rhw;
3907             } else {
3908                 /* That vertex got clipped
3909                  * Contrary to OpenGL it is not dropped completely, it just
3910                  * undergoes a different calculation.
3911                  */
3912                 TRACE("Vertex got clipped\n");
3913                 x += rhw;
3914                 y += rhw;
3915
3916                 x  /= 2;
3917                 y  /= 2;
3918
3919                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3920                  * outside of the main vertex buffer memory. That needs some more
3921                  * investigation...
3922                  */
3923             }
3924
3925             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3926
3927
3928             ( (float *) dest_ptr)[0] = x;
3929             ( (float *) dest_ptr)[1] = y;
3930             ( (float *) dest_ptr)[2] = z;
3931             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3932
3933             dest_ptr += 3 * sizeof(float);
3934
3935             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3936                 dest_ptr += sizeof(float);
3937             }
3938
3939             if(dest_conv) {
3940                 float w = 1 / rhw;
3941                 ( (float *) dest_conv)[0] = x * w;
3942                 ( (float *) dest_conv)[1] = y * w;
3943                 ( (float *) dest_conv)[2] = z * w;
3944                 ( (float *) dest_conv)[3] = w;
3945
3946                 dest_conv += 3 * sizeof(float);
3947
3948                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3949                     dest_conv += sizeof(float);
3950                 }
3951             }
3952         }
3953         if (DestFVF & WINED3DFVF_PSIZE) {
3954             dest_ptr += sizeof(DWORD);
3955             if(dest_conv) dest_conv += sizeof(DWORD);
3956         }
3957         if (DestFVF & WINED3DFVF_NORMAL) {
3958             float *normal =
3959               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
3960             /* AFAIK this should go into the lighting information */
3961             FIXME("Didn't expect the destination to have a normal\n");
3962             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3963             if(dest_conv) {
3964                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
3965             }
3966         }
3967
3968         if (DestFVF & WINED3DFVF_DIFFUSE) {
3969             DWORD *color_d = 
3970               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
3971             if(!color_d) {
3972                 static BOOL warned = FALSE;
3973
3974                 if(!warned) {
3975                     ERR("No diffuse color in source, but destination has one\n");
3976                     warned = TRUE;
3977                 }
3978
3979                 *( (DWORD *) dest_ptr) = 0xffffffff;
3980                 dest_ptr += sizeof(DWORD);
3981
3982                 if(dest_conv) {
3983                     *( (DWORD *) dest_conv) = 0xffffffff;
3984                     dest_conv += sizeof(DWORD);
3985                 }
3986             }
3987             else {
3988                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3989                 if(dest_conv) {
3990                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
3991                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
3992                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
3993                     dest_conv += sizeof(DWORD);
3994                 }
3995             }
3996         }
3997
3998         if (DestFVF & WINED3DFVF_SPECULAR) { 
3999             /* What's the color value in the feedback buffer? */
4000             DWORD *color_s = 
4001               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
4002             if(!color_s) {
4003                 static BOOL warned = FALSE;
4004
4005                 if(!warned) {
4006                     ERR("No specular color in source, but destination has one\n");
4007                     warned = TRUE;
4008                 }
4009
4010                 *( (DWORD *) dest_ptr) = 0xFF000000;
4011                 dest_ptr += sizeof(DWORD);
4012
4013                 if(dest_conv) {
4014                     *( (DWORD *) dest_conv) = 0xFF000000;
4015                     dest_conv += sizeof(DWORD);
4016                 }
4017             }
4018             else {
4019                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
4020                 if(dest_conv) {
4021                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
4022                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
4023                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
4024                     dest_conv += sizeof(DWORD);
4025                 }
4026             }
4027         }
4028
4029         for (tex_index = 0; tex_index < numTextures; tex_index++) {
4030             float *tex_coord =
4031               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
4032                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
4033             if(!tex_coord) {
4034                 ERR("No source texture, but destination requests one\n");
4035                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4036                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
4037             }
4038             else {
4039                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4040                 if(dest_conv) {
4041                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
4042                 }
4043             }
4044         }
4045     }
4046
4047     if(dest_conv) {
4048         GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
4049         checkGLcall("glUnmapBufferARB(GL_ARRAY_BUFFER_ARB)");
4050     }
4051
4052     LEAVE_GL();
4053
4054     return WINED3D_OK;
4055 }
4056 #undef copy_and_next
4057
4058 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
4059     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4060     IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
4061     WineDirect3DVertexStridedData strided;
4062     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
4063
4064     if (!SrcImpl) {
4065         WARN("NULL source vertex buffer\n");
4066         return WINED3DERR_INVALIDCALL;
4067     }
4068     /* We don't need the source vbo because this buffer is only used as
4069      * a source for ProcessVertices. Avoid wasting resources by converting the
4070      * buffer and loading the VBO
4071      */
4072     if(SrcImpl->vbo) {
4073         TRACE("Releasing the source vbo, it won't be needed\n");
4074
4075         if(!SrcImpl->resource.allocatedMemory) {
4076             /* Rescue the data from the buffer */
4077             void *src;
4078             SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
4079             if(!SrcImpl->resource.allocatedMemory) {
4080                 ERR("Out of memory\n");
4081                 return E_OUTOFMEMORY;
4082             }
4083
4084             ENTER_GL();
4085             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
4086             checkGLcall("glBindBufferARB");
4087
4088             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
4089             if(src) {
4090                 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
4091             }
4092
4093             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
4094             checkGLcall("glUnmapBufferARB");
4095         } else {
4096             ENTER_GL();
4097         }
4098
4099         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
4100         checkGLcall("glBindBufferARB");
4101         GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
4102         checkGLcall("glDeleteBuffersARB");
4103         LEAVE_GL();
4104
4105         SrcImpl->vbo = 0;
4106     }
4107
4108     memset(&strided, 0, sizeof(strided));
4109     primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0);
4110
4111     return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
4112 }
4113
4114 /*****
4115  * Get / Set Texture Stage States
4116  * TODO: Verify against dx9 definitions
4117  *****/
4118 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
4119     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4120     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
4121
4122     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
4123
4124     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
4125
4126     /* Reject invalid texture units */
4127     if (Stage >= GL_LIMITS(texture_stages)) {
4128         TRACE("Attempt to access invalid texture rejected\n");
4129         return WINED3DERR_INVALIDCALL;
4130     }
4131
4132     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
4133     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
4134     This->updateStateBlock->textureState[Stage][Type]         = Value;
4135
4136     if (This->isRecordingState) {
4137         TRACE("Recording... not performing anything\n");
4138         return WINED3D_OK;
4139     }
4140
4141     /* Checked after the assignments to allow proper stateblock recording */
4142     if(oldValue == Value) {
4143         TRACE("App is setting the old value over, nothing to do\n");
4144         return WINED3D_OK;
4145     }
4146
4147     if(Stage > This->stateBlock->lowest_disabled_stage &&
4148        StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
4149         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
4150          * Changes in other states are important on disabled stages too
4151          */
4152         return WINED3D_OK;
4153     }
4154
4155     if(Type == WINED3DTSS_COLOROP) {
4156         int i;
4157
4158         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
4159             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
4160              * they have to be disabled
4161              *
4162              * The current stage is dirtified below.
4163              */
4164             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
4165                 TRACE("Additionally dirtifying stage %d\n", i);
4166                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4167             }
4168             This->stateBlock->lowest_disabled_stage = Stage;
4169             TRACE("New lowest disabled: %d\n", Stage);
4170         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
4171             /* Previously disabled stage enabled. Stages above it may need enabling
4172              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
4173              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
4174              *
4175              * Again stage Stage doesn't need to be dirtified here, it is handled below.
4176              */
4177
4178             for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
4179                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
4180                     break;
4181                 }
4182                 TRACE("Additionally dirtifying stage %d due to enable\n", i);
4183                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
4184             }
4185             This->stateBlock->lowest_disabled_stage = i;
4186             TRACE("New lowest disabled: %d\n", i);
4187         }
4188         if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4189             /* TODO: Built a stage -> texture unit mapping for register combiners */
4190         }
4191     }
4192
4193     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
4194
4195     /* Rebuild the stage -> gl texture unit mapping if register combiners are supported
4196      * If there is a pixel shader there will be a 1:1 mapping, no need to touch it. SetPixelShader
4197      * will call FindTexUnitMap too.
4198      */
4199     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4200         IWineD3DDeviceImpl_FindTexUnitMap(This);
4201     }
4202     return WINED3D_OK;
4203 }
4204
4205 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4206     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4207     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4208     *pValue = This->updateStateBlock->textureState[Stage][Type];
4209     return WINED3D_OK;
4210 }
4211
4212 /*****
4213  * Get / Set Texture
4214  *****/
4215 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4216
4217     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4218     IWineD3DBaseTexture   *oldTexture;
4219
4220     oldTexture = This->updateStateBlock->textures[Stage];
4221     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
4222
4223 #if 0 /* TODO: check so vertex textures */
4224     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
4225         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
4226         return WINED3D_OK;
4227     }
4228 #endif
4229
4230     /* Reject invalid texture units */
4231     if (Stage >= GL_LIMITS(sampler_stages) || Stage < 0) {
4232         WARN("Attempt to access invalid texture rejected\n");
4233         return WINED3DERR_INVALIDCALL;
4234     }
4235
4236     if(pTexture != NULL) {
4237         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
4238          */
4239         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
4240             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
4241             return WINED3DERR_INVALIDCALL;
4242         }
4243         This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
4244     }
4245
4246     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
4247     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
4248
4249     This->updateStateBlock->set.textures[Stage]     = TRUE;
4250     This->updateStateBlock->changed.textures[Stage] = TRUE;
4251     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
4252     This->updateStateBlock->textures[Stage]         = pTexture;
4253
4254     /* Handle recording of state blocks */
4255     if (This->isRecordingState) {
4256         TRACE("Recording... not performing anything\n");
4257         return WINED3D_OK;
4258     }
4259
4260     if(oldTexture == pTexture) {
4261         TRACE("App is setting the same texture again, nothing to do\n");
4262         return WINED3D_OK;
4263     }
4264
4265     /** NOTE: MSDN says that setTexture increases the reference count,
4266     * and the the application nust set the texture back to null (or have a leaky application),
4267     * This means we should pass the refcount up to the parent
4268      *******************************/
4269     if (NULL != This->updateStateBlock->textures[Stage]) {
4270         IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
4271         ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
4272
4273         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
4274         if(oldTexture == NULL && Stage < MAX_TEXTURES) {
4275             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
4276              * so the COLOROP and ALPHAOP have to be dirtified.
4277              */
4278             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4279             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4280         }
4281         if(bindCount == 1) {
4282             new->baseTexture.sampler = Stage;
4283         }
4284         /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
4285
4286     }
4287
4288     if (NULL != oldTexture) {
4289         IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
4290         LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
4291
4292         IWineD3DBaseTexture_Release(oldTexture);
4293         if(pTexture == NULL && Stage < MAX_TEXTURES) {
4294             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
4295             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
4296         }
4297
4298         if(bindCount && old->baseTexture.sampler == Stage) {
4299             int i;
4300             /* Have to do a search for the other sampler(s) where the texture is bound to
4301              * Shouldn't happen as long as apps bind a texture only to one stage
4302              */
4303             TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
4304             for(i = 0; i < GL_LIMITS(sampler_stages); i++) {
4305                 if(This->updateStateBlock->textures[i] == oldTexture) {
4306                     old->baseTexture.sampler = i;
4307                     break;
4308                 }
4309             }
4310         }
4311     }
4312
4313     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
4314
4315     /* Verify the texture unit mapping(and rebuild it if needed) if we use nvrcs and no
4316      * pixel shader is used
4317      */
4318     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
4319         IWineD3DDeviceImpl_FindTexUnitMap(This);
4320     }
4321
4322     return WINED3D_OK;
4323 }
4324
4325 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4326     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4327     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
4328
4329     /* Reject invalid texture units */
4330     if (Stage >= GL_LIMITS(sampler_stages)) {
4331         TRACE("Attempt to access invalid texture rejected\n");
4332         return WINED3DERR_INVALIDCALL;
4333     }
4334     *ppTexture=This->stateBlock->textures[Stage];
4335     if (*ppTexture)
4336         IWineD3DBaseTexture_AddRef(*ppTexture);
4337
4338     return WINED3D_OK;
4339 }
4340
4341 /*****
4342  * Get Back Buffer
4343  *****/
4344 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
4345                                                 IWineD3DSurface **ppBackBuffer) {
4346     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4347     IWineD3DSwapChain *swapChain;
4348     HRESULT hr;
4349
4350     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4351
4352     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
4353     if (hr == WINED3D_OK) {
4354         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4355             IWineD3DSwapChain_Release(swapChain);
4356     } else {
4357         *ppBackBuffer = NULL;
4358     }
4359     return hr;
4360 }
4361
4362 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4363     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4364     WARN("(%p) : stub, calling idirect3d for now\n", This);
4365     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4366 }
4367
4368 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4369     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4370     IWineD3DSwapChain *swapChain;
4371     HRESULT hr;
4372
4373     if(iSwapChain > 0) {
4374         hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4375         if (hr == WINED3D_OK) {
4376             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4377             IWineD3DSwapChain_Release(swapChain);
4378         } else {
4379             FIXME("(%p) Error getting display mode\n", This);
4380         }
4381     } else {
4382         /* Don't read the real display mode,
4383            but return the stored mode instead. X11 can't change the color
4384            depth, and some apps are pretty angry if they SetDisplayMode from
4385            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4386
4387            Also don't relay to the swapchain because with ddraw it's possible
4388            that there isn't a swapchain at all */
4389         pMode->Width = This->ddraw_width;
4390         pMode->Height = This->ddraw_height;
4391         pMode->Format = This->ddraw_format;
4392         pMode->RefreshRate = 0;
4393         hr = WINED3D_OK;
4394     }
4395
4396     return hr;
4397 }
4398
4399 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
4400     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4401     TRACE("(%p)->(%p)\n", This, hWnd);
4402
4403     This->ddraw_window = hWnd;
4404     return WINED3D_OK;
4405 }
4406
4407 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
4408     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4409     TRACE("(%p)->(%p)\n", This, hWnd);
4410
4411     *hWnd = This->ddraw_window;
4412     return WINED3D_OK;
4413 }
4414
4415 /*****
4416  * Stateblock related functions
4417  *****/
4418
4419 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4420     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4421     IWineD3DStateBlockImpl *object;
4422     HRESULT temp_result;
4423     
4424     TRACE("(%p)\n", This);
4425     
4426     if (This->isRecordingState) {
4427         return WINED3DERR_INVALIDCALL;
4428     }
4429     
4430     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4431     if (NULL == object ) {
4432         FIXME("(%p)Error allocating memory for stateblock\n", This);
4433         return E_OUTOFMEMORY;
4434     }
4435     TRACE("(%p) created object %p\n", This, object);
4436     object->wineD3DDevice= This;
4437     /** FIXME: object->parent       = parent; **/
4438     object->parent       = NULL;
4439     object->blockType    = WINED3DSBT_ALL;
4440     object->ref          = 1;
4441     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4442     
4443     temp_result = allocate_shader_constants(object);
4444     if (WINED3D_OK != temp_result)
4445         return temp_result;
4446
4447     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4448     This->updateStateBlock = object;
4449     This->isRecordingState = TRUE;
4450
4451     TRACE("(%p) recording stateblock %p\n",This , object);
4452     return WINED3D_OK;
4453 }
4454
4455 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4456     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4457
4458     if (!This->isRecordingState) {
4459         FIXME("(%p) not recording! returning error\n", This);
4460         *ppStateBlock = NULL;
4461         return WINED3DERR_INVALIDCALL;
4462     }
4463
4464     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4465     This->isRecordingState = FALSE;
4466     This->updateStateBlock = This->stateBlock;
4467     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4468     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4469     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4470     return WINED3D_OK;
4471 }
4472
4473 /*****
4474  * Scene related functions
4475  *****/
4476 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4477     /* At the moment we have no need for any functionality at the beginning
4478        of a scene                                                          */
4479     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4480     TRACE("(%p) : stub\n", This);
4481     return WINED3D_OK;
4482 }
4483
4484 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4485     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4486     TRACE("(%p)\n", This);
4487     ENTER_GL();
4488     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4489     glFlush();
4490     checkGLcall("glFlush");
4491
4492     TRACE("End Scene\n");
4493     /* If we're using FBOs this isn't needed */
4494     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO && This->render_targets[0] != NULL) {
4495
4496         /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4497         IUnknown *targetContainer = NULL;
4498         if (WINED3D_OK == IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4499             || WINED3D_OK == IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DDevice, (void **)&targetContainer)) {
4500             TRACE("(%p) : Texture rendertarget %p\n", This ,This->render_targets[0]);
4501             /** always dirtify for now. we must find a better way to see that surface have been modified
4502             (Modifications should will only occur via draw-primitive, but we do need better locking
4503             switching to render-to-texture should remove the overhead though.
4504             */
4505             IWineD3DSurface_SetPBufferState(This->render_targets[0], TRUE /* inPBuffer */, FALSE /* inTexture */);
4506             IWineD3DSurface_AddDirtyRect(This->render_targets[0], NULL);
4507             IWineD3DSurface_PreLoad(This->render_targets[0]);
4508             IWineD3DSurface_SetPBufferState(This->render_targets[0], FALSE /* inPBuffer */, FALSE /* inTexture */);
4509             IUnknown_Release(targetContainer);
4510         }
4511     }
4512     This->sceneEnded = TRUE;
4513     LEAVE_GL();
4514     return WINED3D_OK;
4515 }
4516
4517 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4518                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4519                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4520     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4521     IWineD3DSwapChain *swapChain = NULL;
4522     int i;
4523     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4524
4525     TRACE("(%p) Presenting the frame\n", This);
4526
4527     for(i = 0 ; i < swapchains ; i ++) {
4528
4529         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4530         TRACE("presentinng chain %d, %p\n", i, swapChain);
4531         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4532         IWineD3DSwapChain_Release(swapChain);
4533     }
4534
4535     return WINED3D_OK;
4536 }
4537
4538 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4539                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4540     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4541
4542     /* TODO: From MSDN This method fails if you specify the WINED3DCLEAR_ZBUFFER or WINED3DCLEAR_STENCIL flags when the
4543       render target does not have an attached depth buffer. Similarly, if you specify the WINED3DCLEAR_STENCIL flag
4544       when the depth-buffer format does not contain stencil buffer information, this method fails. */
4545     GLbitfield     glMask = 0;
4546     GLboolean      old_ztest;
4547     GLfloat        old_z_clear_value;
4548     GLint          old_stencil_clear_value;
4549     GLfloat        old_color_clear_value[4];
4550     unsigned int   i;
4551     CONST WINED3DRECT* curRect;
4552
4553     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
4554           Count, pRects, Flags, Z, Stencil);
4555
4556     ENTER_GL();
4557
4558     glEnable(GL_SCISSOR_TEST);
4559     checkGLcall("glEnable GL_SCISSOR_TEST");
4560
4561     if (Count > 0 && pRects) {
4562         curRect = pRects;
4563     } else {
4564         curRect = NULL;
4565     }
4566
4567     /* Only set the values up once, as they are not changing */
4568     if (Flags & WINED3DCLEAR_STENCIL) {
4569         glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4570         glClearStencil(Stencil);
4571         checkGLcall("glClearStencil");
4572         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4573         glStencilMask(0xFFFFFFFF);
4574     }
4575
4576     if (Flags & WINED3DCLEAR_ZBUFFER) {
4577         glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4578         glDepthMask(GL_TRUE);
4579         glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4580         glClearDepth(Z);
4581         checkGLcall("glClearDepth");
4582         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4583     }
4584
4585     if (Flags & WINED3DCLEAR_TARGET) {
4586         TRACE("Clearing screen with glClear to color %x\n", Color);
4587         glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4588         glClearColor(D3DCOLOR_R(Color),
4589                      D3DCOLOR_G(Color),
4590                      D3DCOLOR_B(Color),
4591                      D3DCOLOR_A(Color));
4592         checkGLcall("glClearColor");
4593
4594         /* Clear ALL colors! */
4595         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4596         glMask = glMask | GL_COLOR_BUFFER_BIT;
4597     }
4598
4599     /* Now process each rect in turn */
4600     for (i = 0; i < Count || i == 0; i++) {
4601
4602         if (curRect) {
4603             /* Note gl uses lower left, width/height */
4604             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4605                   curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4606                   curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4607                   curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4608             glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect->y2),
4609                       curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4610             checkGLcall("glScissor");
4611         } else {
4612             glScissor(This->stateBlock->viewport.X,
4613                       (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
4614                       (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4615                       This->stateBlock->viewport.Width,
4616                       This->stateBlock->viewport.Height);
4617             checkGLcall("glScissor");
4618         }
4619
4620         /* Clear the selected rectangle (or full screen) */
4621         glClear(glMask);
4622         checkGLcall("glClear");
4623
4624         /* Step to the next rectangle */
4625         if (curRect) curRect = curRect + sizeof(WINED3DRECT);
4626     }
4627
4628     /* Restore the old values (why..?) */
4629     if (Flags & WINED3DCLEAR_STENCIL) {
4630         glClearStencil(old_stencil_clear_value);
4631         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4632     }
4633     if (Flags & WINED3DCLEAR_ZBUFFER) {
4634         glDepthMask(old_ztest);
4635         glClearDepth(old_z_clear_value);
4636     }
4637     if (Flags & WINED3DCLEAR_TARGET) {
4638         glClearColor(old_color_clear_value[0],
4639                      old_color_clear_value[1],
4640                      old_color_clear_value[2],
4641                      old_color_clear_value[3]);
4642         glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4643                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4644                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4645                     This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4646     }
4647
4648     glDisable(GL_SCISSOR_TEST);
4649     checkGLcall("glDisable");
4650     LEAVE_GL();
4651
4652     return WINED3D_OK;
4653 }
4654
4655 /*****
4656  * Drawing functions
4657  *****/
4658 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4659                                                 UINT PrimitiveCount) {
4660
4661     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4662     This->stateBlock->streamIsUP = FALSE;
4663
4664     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4665                                debug_d3dprimitivetype(PrimitiveType),
4666                                StartVertex, PrimitiveCount);
4667
4668     if(This->stateBlock->loadBaseVertexIndex != 0) {
4669         This->stateBlock->loadBaseVertexIndex = 0;
4670         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4671     }
4672     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4673     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4674                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4675     return WINED3D_OK;
4676 }
4677
4678 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4679 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4680                                                            WINED3DPRIMITIVETYPE PrimitiveType,
4681                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4682
4683     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4684     UINT                 idxStride = 2;
4685     IWineD3DIndexBuffer *pIB;
4686     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
4687
4688     pIB = This->stateBlock->pIndexData;
4689     This->stateBlock->streamIsUP = FALSE;
4690
4691     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
4692           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4693           minIndex, NumVertices, startIndex, primCount);
4694
4695     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4696     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4697         idxStride = 2;
4698     } else {
4699         idxStride = 4;
4700     }
4701
4702     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4703         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4704         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4705     }
4706
4707     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
4708                    idxStride, ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4709
4710     return WINED3D_OK;
4711 }
4712
4713 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4714                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4715                                                     UINT VertexStreamZeroStride) {
4716     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4717
4718     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4719              debug_d3dprimitivetype(PrimitiveType),
4720              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4721
4722     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4723     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4724     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4725     This->stateBlock->streamIsUP = TRUE;
4726     This->stateBlock->loadBaseVertexIndex = 0;
4727
4728     /* TODO: Only mark dirty if drawing from a different UP address */
4729     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4730
4731     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4732                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4733
4734     /* MSDN specifies stream zero settings must be set to NULL */
4735     This->stateBlock->streamStride[0] = 0;
4736     This->stateBlock->streamSource[0] = NULL;
4737
4738     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4739      * the new stream sources or use UP drawing again
4740      */
4741     return WINED3D_OK;
4742 }
4743
4744 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4745                                                              UINT MinVertexIndex, UINT NumVertices,
4746                                                              UINT PrimitiveCount, CONST void* pIndexData,
4747                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4748                                                              UINT VertexStreamZeroStride) {
4749     int                 idxStride;
4750     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4751
4752     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4753              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4754              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4755              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4756
4757     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4758         idxStride = 2;
4759     } else {
4760         idxStride = 4;
4761     }
4762
4763     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4764     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4765     This->stateBlock->streamIsUP = TRUE;
4766     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4767
4768     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4769     This->stateBlock->baseVertexIndex = 0;
4770     This->stateBlock->loadBaseVertexIndex = 0;
4771     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4772     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4773
4774     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4775
4776     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4777     This->stateBlock->streamSource[0] = NULL;
4778     This->stateBlock->streamStride[0] = 0;
4779     This->stateBlock->pIndexData = NULL;
4780     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4781      * SetStreamSource to specify a vertex buffer
4782      */
4783
4784     return WINED3D_OK;
4785 }
4786
4787 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4788     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4789
4790     /* Mark the state dirty until we have nicer tracking
4791      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4792      * that value.
4793      */
4794     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4795     This->stateBlock->baseVertexIndex = 0;
4796     This->up_strided = DrawPrimStrideData;
4797     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
4798     This->up_strided = NULL;
4799     return WINED3D_OK;
4800 }
4801  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4802 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4803     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4804     HRESULT hr = WINED3D_OK;
4805     WINED3DRESOURCETYPE sourceType;
4806     WINED3DRESOURCETYPE destinationType;
4807     int i ,levels;
4808
4809     /* TODO: think about moving the code into IWineD3DBaseTexture  */
4810
4811     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4812
4813     /* verify that the source and destination textures aren't NULL */
4814     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4815         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4816              This, pSourceTexture, pDestinationTexture);
4817         hr = WINED3DERR_INVALIDCALL;
4818     }
4819
4820     if (pSourceTexture == pDestinationTexture) {
4821         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4822              This, pSourceTexture, pDestinationTexture);
4823         hr = WINED3DERR_INVALIDCALL;
4824     }
4825     /* Verify that the source and destination textures are the same type */
4826     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
4827     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4828
4829     if (sourceType != destinationType) {
4830         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
4831              This);
4832         hr = WINED3DERR_INVALIDCALL;
4833     }
4834
4835     /* check that both textures have the identical numbers of levels  */
4836     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4837         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4838         hr = WINED3DERR_INVALIDCALL;
4839     }
4840
4841     if (WINED3D_OK == hr) {
4842
4843         /* Make sure that the destination texture is loaded */
4844         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4845
4846         /* Update every surface level of the texture */
4847         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4848
4849         switch (sourceType) {
4850         case WINED3DRTYPE_TEXTURE:
4851             {
4852                 IWineD3DSurface *srcSurface;
4853                 IWineD3DSurface *destSurface;
4854
4855                 for (i = 0 ; i < levels ; ++i) {
4856                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
4857                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4858                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4859                     IWineD3DSurface_Release(srcSurface);
4860                     IWineD3DSurface_Release(destSurface);
4861                     if (WINED3D_OK != hr) {
4862                         WARN("(%p) : Call to update surface failed\n", This);
4863                         return hr;
4864                     }
4865                 }
4866             }
4867             break;
4868         case WINED3DRTYPE_CUBETEXTURE:
4869             {
4870                 IWineD3DSurface *srcSurface;
4871                 IWineD3DSurface *destSurface;
4872                 WINED3DCUBEMAP_FACES faceType;
4873
4874                 for (i = 0 ; i < levels ; ++i) {
4875                     /* Update each cube face */
4876                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4877                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
4878                         if (WINED3D_OK != hr) {
4879                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4880                         } else {
4881                             TRACE("Got srcSurface %p\n", srcSurface);
4882                         }
4883                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4884                         if (WINED3D_OK != hr) {
4885                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4886                         } else {
4887                             TRACE("Got desrSurface %p\n", destSurface);
4888                         }
4889                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4890                         IWineD3DSurface_Release(srcSurface);
4891                         IWineD3DSurface_Release(destSurface);
4892                         if (WINED3D_OK != hr) {
4893                             WARN("(%p) : Call to update surface failed\n", This);
4894                             return hr;
4895                         }
4896                     }
4897                 }
4898             }
4899             break;
4900 #if 0 /* TODO: Add support for volume textures */
4901         case WINED3DRTYPE_VOLUMETEXTURE:
4902             {
4903                 IWineD3DVolume  srcVolume  = NULL;
4904                 IWineD3DSurface destVolume = NULL;
4905
4906                 for (i = 0 ; i < levels ; ++i) {
4907                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
4908                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4909                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4910                     IWineD3DVolume_Release(srcSurface);
4911                     IWineD3DVolume_Release(destSurface);
4912                     if (WINED3D_OK != hr) {
4913                         WARN("(%p) : Call to update volume failed\n", This);
4914                         return hr;
4915                     }
4916                 }
4917             }
4918             break;
4919 #endif
4920         default:
4921             FIXME("(%p) : Unsupported source and destination type\n", This);
4922             hr = WINED3DERR_INVALIDCALL;
4923         }
4924     }
4925
4926     return hr;
4927 }
4928
4929 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4930     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4931     /** TODO: remove remove casts to IWineD3DSurfaceImpl *
4932     *  NOTE It may be best to move the code into surface to occomplish this
4933     ****************************************/
4934
4935     WINED3DSURFACE_DESC surfaceDesc;
4936     unsigned int surfaceWidth, surfaceHeight;
4937     glDescriptor *targetGlDescription  = NULL;
4938     glDescriptor *surfaceGlDescription = NULL;
4939     IWineD3DSwapChainImpl *container = NULL;
4940     
4941     IWineD3DSurface_GetGlDesc(pRenderTarget, &targetGlDescription);
4942     IWineD3DSurface_GetGlDesc(pSurface,      &surfaceGlDescription);
4943     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
4944
4945     surfaceDesc.Width  = &surfaceWidth;
4946     surfaceDesc.Height = &surfaceHeight;
4947     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
4948    /* check to see if it's the backbuffer or the frontbuffer being requested (to make sure the data is up to date)*/
4949
4950     /* Ok, I may need to setup some kind of active swapchain reference on the device */
4951     IWineD3DSurface_GetContainer(pRenderTarget, &IID_IWineD3DSwapChain, (void **)&container);
4952     ENTER_GL();
4953     /* TODO: opengl Context switching for swapchains etc... */
4954     if (NULL != container  || pRenderTarget == This->render_targets[0] || pRenderTarget == This->depthStencilBuffer) {
4955         if (NULL != container  && (pRenderTarget == container->backBuffer[0])) {
4956             glReadBuffer(GL_BACK);
4957             vcheckGLcall("glReadBuffer(GL_BACK)");
4958         } else if ((NULL != container  && (pRenderTarget == container->frontBuffer)) || (pRenderTarget == This->render_targets[0])) {
4959             glReadBuffer(GL_FRONT);
4960             vcheckGLcall("glReadBuffer(GL_FRONT)");
4961         } else if (pRenderTarget == This->depthStencilBuffer) {
4962             FIXME("Reading of depthstencil not yet supported\n");
4963         }
4964
4965         glReadPixels(0,
4966                     0,
4967                     surfaceWidth,
4968                     surfaceHeight,
4969                     surfaceGlDescription->glFormat,
4970                     surfaceGlDescription->glType,
4971                     (void *)IWineD3DSurface_GetData(pSurface));
4972         vcheckGLcall("glReadPixels(...)");
4973         if(NULL != container ){
4974             IWineD3DSwapChain_Release((IWineD3DSwapChain*) container);
4975         }
4976     } else {
4977         IWineD3DBaseTexture *container;
4978         GLenum textureDimensions = GL_TEXTURE_2D;
4979
4980         if (WINED3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DBaseTexture, (void **)&container)) {
4981             textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(container);
4982             IWineD3DBaseTexture_Release(container);
4983         }
4984         /* TODO: 2D -> Cube surface coppies etc.. */
4985         if (surfaceGlDescription->target != textureDimensions) {
4986             FIXME("(%p) : Texture dimension mismatch\n", This);
4987         }
4988         glEnable(textureDimensions);
4989         vcheckGLcall("glEnable(GL_TEXTURE_...)");
4990         /* FIXME: this isn't correct, it need to add a dirty rect if nothing else... */
4991         glBindTexture(targetGlDescription->target, targetGlDescription->textureName);
4992         vcheckGLcall("glBindTexture");
4993         glGetTexImage(surfaceGlDescription->target,
4994                         surfaceGlDescription->level,
4995                         surfaceGlDescription->glFormat,
4996                         surfaceGlDescription->glType,
4997                         (void *)IWineD3DSurface_GetData(pSurface));
4998         glDisable(textureDimensions);
4999         vcheckGLcall("glDisable(GL_TEXTURE_...)");
5000
5001     }
5002     LEAVE_GL();
5003     return WINED3D_OK;
5004 }
5005
5006 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
5007     IWineD3DSwapChain *swapChain;
5008     HRESULT hr;
5009     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5010     if(hr == WINED3D_OK) {
5011         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
5012                 IWineD3DSwapChain_Release(swapChain);
5013     }
5014     return hr;
5015 }
5016
5017 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
5018     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5019     /* return a sensible default */
5020     *pNumPasses = 1;
5021     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
5022     FIXME("(%p) : stub\n", This);
5023     return WINED3D_OK;
5024 }
5025
5026 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
5027     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5028     int j;
5029     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5030     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5031         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5032         return WINED3DERR_INVALIDCALL;
5033     }
5034     for (j = 0; j < 256; ++j) {
5035         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
5036         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
5037         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
5038         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
5039     }
5040     TRACE("(%p) : returning\n", This);
5041     return WINED3D_OK;
5042 }
5043
5044 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
5045     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5046     int j;
5047     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5048     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5049         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5050         return WINED3DERR_INVALIDCALL;
5051     }
5052     for (j = 0; j < 256; ++j) {
5053         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
5054         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
5055         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
5056         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
5057     }
5058     TRACE("(%p) : returning\n", This);
5059     return WINED3D_OK;
5060 }
5061
5062 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
5063     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5064     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
5065     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
5066         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
5067         return WINED3DERR_INVALIDCALL;
5068     }
5069     /*TODO: stateblocks */
5070     This->currentPalette = PaletteNumber;
5071     TRACE("(%p) : returning\n", This);
5072     return WINED3D_OK;
5073 }
5074
5075 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
5076     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5077     if (PaletteNumber == NULL) {
5078         WARN("(%p) : returning Invalid Call\n", This);
5079         return WINED3DERR_INVALIDCALL;
5080     }
5081     /*TODO: stateblocks */
5082     *PaletteNumber = This->currentPalette;
5083     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
5084     return WINED3D_OK;
5085 }
5086
5087 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
5088     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5089     static BOOL showFixmes = TRUE;
5090     if (showFixmes) {
5091         FIXME("(%p) : stub\n", This);
5092         showFixmes = FALSE;
5093     }
5094
5095     This->softwareVertexProcessing = bSoftware;
5096     return WINED3D_OK;
5097 }
5098
5099
5100 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
5101     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5102     static BOOL showFixmes = TRUE;
5103     if (showFixmes) {
5104         FIXME("(%p) : stub\n", This);
5105         showFixmes = FALSE;
5106     }
5107     return This->softwareVertexProcessing;
5108 }
5109
5110
5111 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
5112     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5113     IWineD3DSwapChain *swapChain;
5114     HRESULT hr;
5115
5116     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
5117
5118     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
5119     if(hr == WINED3D_OK){
5120         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
5121         IWineD3DSwapChain_Release(swapChain);
5122     }else{
5123         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
5124     }
5125     return hr;
5126 }
5127
5128
5129 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
5130     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5131     static BOOL showfixmes = TRUE;
5132     if(nSegments != 0.0f) {
5133         if( showfixmes) {
5134             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
5135             showfixmes = FALSE;
5136         }
5137     }
5138     return WINED3D_OK;
5139 }
5140
5141 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
5142     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5143     static BOOL showfixmes = TRUE;
5144     if( showfixmes) {
5145         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
5146         showfixmes = FALSE;
5147     }
5148     return 0.0f;
5149 }
5150
5151 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
5152     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
5153     /** TODO: remove casts to IWineD3DSurfaceImpl
5154      *       NOTE: move code to surface to accomplish this
5155       ****************************************/
5156     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
5157     int srcWidth, srcHeight;
5158     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
5159     WINED3DFORMAT destFormat, srcFormat;
5160     UINT          destSize;
5161     int srcLeft, destLeft, destTop;
5162     WINED3DPOOL       srcPool, destPool;
5163     int offset    = 0;
5164     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
5165     glDescriptor *glDescription = NULL;
5166     GLenum textureDimensions = GL_TEXTURE_2D;
5167     IWineD3DBaseTexture *baseTexture;
5168
5169     WINED3DSURFACE_DESC  winedesc;
5170
5171     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
5172     memset(&winedesc, 0, sizeof(winedesc));
5173     winedesc.Width  = &srcSurfaceWidth;
5174     winedesc.Height = &srcSurfaceHeight;
5175     winedesc.Pool   = &srcPool;
5176     winedesc.Format = &srcFormat;
5177
5178     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
5179
5180     winedesc.Width  = &destSurfaceWidth;
5181     winedesc.Height = &destSurfaceHeight;
5182     winedesc.Pool   = &destPool;
5183     winedesc.Format = &destFormat;
5184     winedesc.Size   = &destSize;
5185
5186     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5187
5188     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
5189         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
5190         return WINED3DERR_INVALIDCALL;
5191     }
5192
5193     if (destFormat == WINED3DFMT_UNKNOWN) {
5194         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
5195         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
5196
5197         /* Get the update surface description */
5198         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
5199     }
5200
5201     /* Make sure the surface is loaded and up to date */
5202     IWineD3DSurface_PreLoad(pDestinationSurface);
5203
5204     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
5205
5206     ENTER_GL();
5207
5208     /* this needs to be done in lines if the sourceRect != the sourceWidth */
5209     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
5210     srcHeight  = pSourceRect ? pSourceRect->top   - pSourceRect->bottom : srcSurfaceHeight;
5211     srcLeft    = pSourceRect ? pSourceRect->left : 0;
5212     destLeft   = pDestPoint  ? pDestPoint->x : 0;
5213     destTop    = pDestPoint  ? pDestPoint->y : 0;
5214
5215
5216     /* This function doesn't support compressed textures
5217     the pitch is just bytesPerPixel * width */
5218     if(srcWidth != srcSurfaceWidth  || srcLeft ){
5219         rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
5220         offset   += srcLeft * pSrcSurface->bytesPerPixel;
5221         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
5222     }
5223     /* TODO DXT formats */
5224
5225     if(pSourceRect != NULL && pSourceRect->top != 0){
5226        offset +=  pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
5227     }
5228     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
5229     ,This
5230     ,glDescription->level
5231     ,destLeft
5232     ,destTop
5233     ,srcWidth
5234     ,srcHeight
5235     ,glDescription->glFormat
5236     ,glDescription->glType
5237     ,IWineD3DSurface_GetData(pSourceSurface)
5238     );
5239
5240     /* Sanity check */
5241     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
5242
5243         /* need to lock the surface to get the data */
5244         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
5245     }
5246
5247     /* TODO: Cube and volume support */
5248     if(rowoffset != 0){
5249         /* not a whole row so we have to do it a line at a time */
5250         int j;
5251
5252         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
5253         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
5254
5255         for(j = destTop ; j < (srcHeight + destTop) ; j++){
5256
5257                 glTexSubImage2D(glDescription->target
5258                     ,glDescription->level
5259                     ,destLeft
5260                     ,j
5261                     ,srcWidth
5262                     ,1
5263                     ,glDescription->glFormat
5264                     ,glDescription->glType
5265                     ,data /* could be quicker using */
5266                 );
5267             data += rowoffset;
5268         }
5269
5270     } else { /* Full width, so just write out the whole texture */
5271
5272         if (WINED3DFMT_DXT1 == destFormat ||
5273             WINED3DFMT_DXT2 == destFormat ||
5274             WINED3DFMT_DXT3 == destFormat ||
5275             WINED3DFMT_DXT4 == destFormat ||
5276             WINED3DFMT_DXT5 == destFormat) {
5277             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
5278                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
5279                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
5280                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
5281                 } if (destFormat != srcFormat) {
5282                     FIXME("Updating mixed format compressed texture is not curretly support\n");
5283                 } else {
5284                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5285                                                         glDescription->level,
5286                                                         glDescription->glFormatInternal,
5287                                                         srcWidth,
5288                                                         srcHeight,
5289                                                         0,
5290                                                         destSize,
5291                                                         IWineD3DSurface_GetData(pSourceSurface));
5292                 }
5293             } else {
5294                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5295             }
5296
5297
5298         } else {
5299             if (NP2_REPACK == wined3d_settings.nonpower2_mode) {
5300
5301                 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5302                 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5303                 data returned by GetData non-power2 width/height with hardware non-power2
5304                 pow2Width/height are set to surface width height, repacking isn't needed so it
5305                 doesn't matter which function gets called. */
5306                 glTexSubImage2D(glDescription->target
5307                         ,glDescription->level
5308                         ,destLeft
5309                         ,destTop
5310                         ,srcWidth
5311                         ,srcHeight
5312                         ,glDescription->glFormat
5313                         ,glDescription->glType
5314                         ,IWineD3DSurface_GetData(pSourceSurface)
5315                     );
5316             } else {
5317
5318                 /* not repacked, the data returned by IWineD3DSurface_GetData is pow2Width x pow2Height */
5319                 glTexSubImage2D(glDescription->target
5320                     ,glDescription->level
5321                     ,destLeft
5322                     ,destTop
5323                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Width
5324                     ,((IWineD3DSurfaceImpl *)pSourceSurface)->pow2Height
5325                     ,glDescription->glFormat
5326                     ,glDescription->glType
5327                     ,IWineD3DSurface_GetData(pSourceSurface)
5328                 );
5329             }
5330
5331         }
5332      }
5333     checkGLcall("glTexSubImage2D");
5334     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
5335
5336     /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5337      * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5338      * surface bigger than it needs to be hmm.. */
5339     if (WINED3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5340         textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5341         IWineD3DBaseTexture_Release(baseTexture);
5342     }
5343
5344     glDisable(textureDimensions); /* This needs to be managed better.... */
5345     LEAVE_GL();
5346
5347     return WINED3D_OK;
5348 }
5349
5350 /* Implementation details at http://developer.nvidia.com/attach/6494
5351 and
5352 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5353 hmm.. no longer supported use
5354 OpenGL evaluators or  tessellate surfaces within your application.
5355 */
5356
5357 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5358 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
5359     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5360     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
5361     FIXME("(%p) : Stub\n", This);
5362     return WINED3D_OK;
5363
5364 }
5365
5366 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5367 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
5368     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5369     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
5370     FIXME("(%p) : Stub\n", This);
5371     return WINED3D_OK;
5372 }
5373
5374 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5375     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5376     TRACE("(%p) Handle(%d)\n", This, Handle);
5377     FIXME("(%p) : Stub\n", This);
5378     return WINED3D_OK;
5379 }
5380
5381 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
5382     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5383     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
5384     DDBLTFX BltFx;
5385     TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
5386
5387     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
5388         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
5389         return WINED3DERR_INVALIDCALL;
5390     }
5391
5392     /* Just forward this to the DirectDraw blitting engine */
5393     memset(&BltFx, 0, sizeof(BltFx));
5394     BltFx.dwSize = sizeof(BltFx);
5395     BltFx.u5.dwFillColor = color;
5396     return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
5397 }
5398
5399 /* rendertarget and deptth stencil functions */
5400 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5401     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5402
5403     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5404         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5405         return WINED3DERR_INVALIDCALL;
5406     }
5407
5408     *ppRenderTarget = This->render_targets[RenderTargetIndex];
5409     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5410     /* Note inc ref on returned surface */
5411     if(*ppRenderTarget != NULL)
5412         IWineD3DSurface_AddRef(*ppRenderTarget);
5413     return WINED3D_OK;
5414 }
5415
5416 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
5417     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5418     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
5419     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
5420     IWineD3DSwapChainImpl *Swapchain;
5421     HRESULT hr;
5422
5423     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
5424
5425     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
5426     if(hr != WINED3D_OK) {
5427         ERR("Can't get the swapchain\n");
5428         return hr;
5429     }
5430
5431     /* Make sure to release the swapchain */
5432     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
5433
5434     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
5435         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5436         return WINED3DERR_INVALIDCALL;
5437     }
5438     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
5439         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5440         return WINED3DERR_INVALIDCALL;
5441     }
5442
5443     if(Swapchain->frontBuffer != Front) {
5444         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
5445
5446         if(Swapchain->frontBuffer)
5447             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
5448         Swapchain->frontBuffer = Front;
5449
5450         if(Swapchain->frontBuffer) {
5451             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
5452         }
5453     }
5454
5455     if(Back && !Swapchain->backBuffer) {
5456         /* We need memory for the back buffer array - only one back buffer this way */
5457         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
5458         if(!Swapchain->backBuffer) {
5459             ERR("Out of memory\n");
5460             return E_OUTOFMEMORY;
5461         }
5462     }
5463
5464     if(Swapchain->backBuffer[0] != Back) {
5465         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
5466         ENTER_GL();
5467         if(!Swapchain->backBuffer[0]) {
5468             /* GL was told to draw to the front buffer at creation,
5469              * undo that
5470              */
5471             glDrawBuffer(GL_BACK);
5472             checkGLcall("glDrawBuffer(GL_BACK)");
5473             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
5474             Swapchain->presentParms.BackBufferCount = 1;
5475         } else if (!Back) {
5476             /* That makes problems - disable for now */
5477             /* glDrawBuffer(GL_FRONT); */
5478             checkGLcall("glDrawBuffer(GL_FRONT)");
5479             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
5480             Swapchain->presentParms.BackBufferCount = 0;
5481         }
5482         LEAVE_GL();
5483
5484         if(Swapchain->backBuffer[0])
5485             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
5486         Swapchain->backBuffer[0] = Back;
5487
5488         if(Swapchain->backBuffer[0]) {
5489             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
5490         } else {
5491             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
5492         }
5493
5494     }
5495
5496     return WINED3D_OK;
5497 }
5498
5499 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5500     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5501     *ppZStencilSurface = This->depthStencilBuffer;
5502     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5503
5504     if(*ppZStencilSurface != NULL) {
5505         /* Note inc ref on returned surface */
5506         IWineD3DSurface_AddRef(*ppZStencilSurface);
5507     }
5508     return WINED3D_OK;
5509 }
5510
5511 static void bind_fbo(IWineD3DDevice *iface) {
5512     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5513
5514     if (!This->fbo) {
5515         GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
5516         checkGLcall("glGenFramebuffersEXT()");
5517     }
5518     GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
5519     checkGLcall("glBindFramebuffer()");
5520 }
5521
5522 /* TODO: Handle stencil attachments */
5523 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5524     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5525     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5526
5527     This->depth_copy_state = WINED3D_DCS_NO_COPY;
5528
5529     bind_fbo(iface);
5530
5531     if (depth_stencil_impl) {
5532         GLenum texttarget, target;
5533         GLint old_binding = 0;
5534
5535         IWineD3DSurface_PreLoad(depth_stencil);
5536         texttarget = depth_stencil_impl->glDescription.target;
5537         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5538
5539         glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5540         glBindTexture(target, depth_stencil_impl->glDescription.textureName);
5541         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5542         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5543         glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5544         glBindTexture(target, old_binding);
5545
5546         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5547         checkGLcall("glFramebufferTexture2DEXT()");
5548     } else {
5549         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5550         checkGLcall("glFramebufferTexture2DEXT()");
5551     }
5552
5553     if (!This->render_offscreen) {
5554         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5555         checkGLcall("glBindFramebuffer()");
5556     }
5557 }
5558
5559 static void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5560     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5561     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5562
5563     if (idx >= GL_LIMITS(buffers)) {
5564         ERR("%p : Trying to set render target %d, but only %d supported\n", This, idx, GL_LIMITS(buffers));
5565     }
5566
5567     bind_fbo(iface);
5568
5569     if (rtimpl) {
5570         GLenum texttarget, target;
5571         GLint old_binding = 0;
5572
5573         IWineD3DSurface_PreLoad(render_target);
5574         texttarget = rtimpl->glDescription.target;
5575         target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5576
5577         glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5578         glBindTexture(target, rtimpl->glDescription.textureName);
5579         glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5580         glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5581         glBindTexture(target, old_binding);
5582
5583         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, rtimpl->glDescription.textureName, 0));
5584         checkGLcall("glFramebufferTexture2DEXT()");
5585
5586         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5587     } else {
5588         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5589         checkGLcall("glFramebufferTexture2DEXT()");
5590
5591         This->draw_buffers[idx] = GL_NONE;
5592     }
5593
5594     if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5595         GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5596         checkGLcall("glDrawBuffers()");
5597     }
5598
5599     if (!This->render_offscreen) {
5600         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5601         checkGLcall("glBindFramebuffer()");
5602     }
5603 }
5604
5605 /* internal static helper functions */
5606 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5607                                                 IWineD3DSurface *RenderSurface);
5608
5609 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5610     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5611     HRESULT  hr = WINED3D_OK;
5612     WINED3DVIEWPORT viewport;
5613
5614     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5615
5616     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5617         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5618         return WINED3DERR_INVALIDCALL;
5619     }
5620
5621     /* MSDN says that null disables the render target
5622     but a device must always be associated with a render target
5623     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5624
5625     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5626     for more details
5627     */
5628     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5629         FIXME("Trying to set render target 0 to NULL\n");
5630         return WINED3DERR_INVALIDCALL;
5631     }
5632     /* TODO: replace Impl* usage with interface usage */
5633     if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5634         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);
5635         return WINED3DERR_INVALIDCALL;
5636     }
5637     /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5638      *        builds, but I think wine counts as a 'debug' build for now.
5639       ******************************/
5640     /* If we are trying to set what we already have, don't bother */
5641     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5642         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5643     } else {
5644         /* Otherwise, set the render target up */
5645
5646         if (!This->sceneEnded) {
5647             IWineD3DDevice_EndScene(iface);
5648         }
5649         TRACE("clearing renderer\n");
5650         /* IWineD3DDeviceImpl_CleanRender(iface); */
5651         /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5652         depending on the renter target implementation being used.
5653         A shared context implementation will share all buffers between all rendertargets (including swapchains),
5654         implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5655         stencil buffer and incure an extra memory overhead */
5656         if (RenderTargetIndex == 0) {
5657             hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5658         } else {
5659             hr = WINED3D_OK;
5660         }
5661
5662         /* Replace the render target */
5663         if (This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5664         This->render_targets[RenderTargetIndex] = pRenderTarget;
5665         if (pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5666
5667         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5668             set_render_target_fbo(iface, RenderTargetIndex, pRenderTarget);
5669         }
5670     }
5671
5672     if (SUCCEEDED(hr)) {
5673         /* Finally, reset the viewport as the MSDN states. */
5674         /* TODO: Replace impl usage */
5675         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5676         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5677         viewport.X      = 0;
5678         viewport.Y      = 0;
5679         viewport.MaxZ   = 1.0f;
5680         viewport.MinZ   = 0.0f;
5681         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5682     } else {
5683         FIXME("Unknown error setting the render target\n");
5684     }
5685     This->sceneEnded = FALSE;
5686     return hr;
5687 }
5688
5689 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5690     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5691     HRESULT  hr = WINED3D_OK;
5692     IWineD3DSurface *tmp;
5693
5694     TRACE("(%p) Swapping z-buffer\n",This);
5695
5696     if (pNewZStencil == This->stencilBufferTarget) {
5697         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5698     } else {
5699         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5700         * depending on the renter target implementation being used.
5701         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5702         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5703         * stencil buffer and incure an extra memory overhead
5704          ******************************************************/
5705
5706
5707         tmp = This->stencilBufferTarget;
5708         This->stencilBufferTarget = pNewZStencil;
5709         /* should we be calling the parent or the wined3d surface? */
5710         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5711         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5712         hr = WINED3D_OK;
5713         /** TODO: glEnable/glDisable on depth/stencil    depending on
5714          *   pNewZStencil is NULL and the depth/stencil is enabled in d3d
5715           **********************************************************/
5716         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5717             set_depth_stencil_fbo(iface, pNewZStencil);
5718         }
5719     }
5720
5721     return hr;
5722 }
5723
5724
5725 #ifdef GL_VERSION_1_3
5726 /* Internal functions not in DirectX */
5727  /** TODO: move this off to the opengl context manager
5728  *(the swapchain doesn't need to know anything about offscreen rendering!)
5729   ****************************************************/
5730
5731 static HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5732 {
5733     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5734
5735     TRACE("(%p), %p\n", This, swapchain);
5736
5737     if (swapchain->win != swapchain->drawable) {
5738         /* Set everything back the way it ws */
5739         swapchain->render_ctx = swapchain->glCtx;
5740         swapchain->drawable   = swapchain->win;
5741     }
5742     return WINED3D_OK;
5743 }
5744
5745 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5746 static HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5747     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5748     int i;
5749     unsigned int width;
5750     unsigned int height;
5751     WINED3DFORMAT format;
5752     WINED3DSURFACE_DESC surfaceDesc;
5753     memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5754     surfaceDesc.Width  = &width;
5755     surfaceDesc.Height = &height;
5756     surfaceDesc.Format = &format;
5757     IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5758     *context = NULL;
5759     /* I need a get width/height function (and should do something with the format) */
5760     for (i = 0; i < CONTEXT_CACHE; ++i) {
5761         /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5762         ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5763         the pSurface can be set to 0 allowing it to be reused from cache **/
5764         if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5765           && (!pbuffer_per_surface || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5766             *context = &This->contextCache[i];
5767             break;
5768         }
5769         if (This->contextCache[i].Width == 0) {
5770             This->contextCache[i].pSurface = pSurface;
5771             This->contextCache[i].Width    = width;
5772             This->contextCache[i].Height   = height;
5773             *context = &This->contextCache[i];
5774             break;
5775         }
5776     }
5777     if (i == CONTEXT_CACHE) {
5778         int minUsage = 0x7FFFFFFF; /* MAX_INT */
5779         glContext *dropContext = 0;
5780         for (i = 0; i < CONTEXT_CACHE; i++) {
5781             if (This->contextCache[i].usedcount < minUsage) {
5782                 dropContext = &This->contextCache[i];
5783                 minUsage = This->contextCache[i].usedcount;
5784             }
5785         }
5786         /* clean up the context (this doesn't work for ATI at the moment */
5787 #if 0
5788         glXDestroyContext(swapchain->display, dropContext->context);
5789         glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5790 #endif
5791         FIXME("Leak\n");
5792         dropContext->Width = 0;
5793         dropContext->pSurface = pSurface;
5794         *context = dropContext;
5795     } else {
5796         if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5797           for (i = 0; i < CONTEXT_CACHE; i++) {
5798              This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5799           }
5800         }
5801     }
5802     if (*context != NULL)
5803         return WINED3D_OK;
5804     else
5805         return E_OUTOFMEMORY;
5806 }
5807 #endif
5808
5809 /* Reapply the device stateblock */
5810 static void device_reapply_stateblock(IWineD3DDeviceImpl* This) {
5811
5812     BOOL oldRecording;  
5813     IWineD3DStateBlockImpl *oldUpdateStateBlock;
5814     DWORD i;
5815
5816     /* Disable recording */
5817     oldUpdateStateBlock = This->updateStateBlock;
5818     oldRecording= This->isRecordingState;
5819     This->isRecordingState = FALSE;
5820     This->updateStateBlock = This->stateBlock;
5821
5822     /* Reapply the state block */ 
5823     IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5824
5825     /* Temporaryily mark all render states dirty to force reapplication
5826      * until the context management for is integrated with the state management
5827      * The same for the pixel shader, vertex declaration and vertex shader
5828      * Sampler states and texture stage states are marked
5829      * dirty my StateBlock::Apply already.
5830      */
5831     for(i = 1; i < WINEHIGHEST_RENDER_STATE; i++) {
5832         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(i));
5833     }
5834     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
5835     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
5836     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
5837
5838     /* Restore recording */
5839     This->isRecordingState = oldRecording;
5840     This->updateStateBlock = oldUpdateStateBlock;
5841 }
5842
5843 /* Set offscreen rendering. When rendering offscreen the surface will be
5844  * rendered upside down to compensate for the fact that D3D texture coordinates
5845  * are flipped compared to GL texture coordinates. The cullmode is affected by
5846  * this, so it must be updated. To update the cullmode stateblock recording has
5847  * to be temporarily disabled. The new state management code will hopefully
5848  * make this unnecessary */
5849 static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
5850
5851     BOOL oldRecording;
5852     IWineD3DStateBlockImpl *oldUpdateStateBlock;
5853
5854     /* Nothing to update, return. */
5855     if (This->render_offscreen == isTexture) return;
5856
5857     /* Disable recording */
5858     oldUpdateStateBlock = This->updateStateBlock;
5859     oldRecording= This->isRecordingState;
5860     This->isRecordingState = FALSE;
5861     This->updateStateBlock = This->stateBlock;
5862
5863     This->render_offscreen = isTexture;
5864     if (This->depth_copy_state != WINED3D_DCS_NO_COPY) {
5865         This->depth_copy_state = WINED3D_DCS_COPY;
5866     }
5867     This->last_was_rhw = FALSE;
5868     /* Viewport state will reapply the projection matrix for now */
5869     IWineD3DDeviceImpl_MarkStateDirty(This, WINED3DRS_CULLMODE);
5870
5871     /* Restore recording */
5872     This->isRecordingState = oldRecording;
5873     This->updateStateBlock = oldUpdateStateBlock;
5874 }
5875
5876 /* Returns an array of compatible FBconfig(s).
5877  * The array must be freed with XFree. Requires ENTER_GL() */
5878
5879 static GLXFBConfig* device_find_fbconfigs(
5880     IWineD3DDeviceImpl* This,
5881     IWineD3DSwapChainImpl* implicitSwapchainImpl,
5882     IWineD3DSurface* RenderSurface) {
5883
5884     GLXFBConfig* cfgs = NULL;
5885     int nCfgs = 0;
5886     int attribs[256];
5887     int nAttribs = 0;
5888
5889     IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5890     WINED3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5891     WINED3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5892
5893     /**TODO:
5894         if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off, 
5895         it StencilSurface != NULL && zBufferTarget == NULL switch it on
5896     */
5897
5898 #define PUSH1(att)        attribs[nAttribs++] = (att);
5899 #define PUSH2(att,value)  attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5900
5901     /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5902
5903     PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5904     PUSH2(GLX_X_RENDERABLE,  TRUE);
5905     PUSH2(GLX_DOUBLEBUFFER,  TRUE);
5906     TRACE("calling makeglcfg\n");
5907     D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5908     PUSH1(None);
5909     TRACE("calling chooseFGConfig\n");
5910     cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
5911                              DefaultScreen(implicitSwapchainImpl->display),
5912                              attribs, &nCfgs);
5913     if (cfgs == NULL) {
5914         /* OK we didn't find the exact config, so use any reasonable match */
5915         /* TODO: fill in the 'requested' and 'current' depths, and make sure that's
5916            why we failed. */
5917         static BOOL show_message = TRUE;
5918         if (show_message) {
5919             ERR("Failed to find exact match, finding alternative but you may "
5920                 "suffer performance issues, try changing xfree's depth to match the requested depth\n");
5921             show_message = FALSE;
5922         }
5923         nAttribs = 0;
5924         PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5925         /* PUSH2(GLX_X_RENDERABLE,  TRUE); */
5926         PUSH2(GLX_RENDER_TYPE,   GLX_RGBA_BIT);
5927         PUSH2(GLX_DOUBLEBUFFER, FALSE);
5928         TRACE("calling makeglcfg\n");
5929         D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5930         PUSH1(None);
5931         cfgs = glXChooseFBConfig(implicitSwapchainImpl->display,
5932                                  DefaultScreen(implicitSwapchainImpl->display),
5933                                  attribs, &nCfgs);
5934     }
5935                                                                                                                                                                       
5936     if (cfgs == NULL) {
5937         ERR("Could not get a valid FBConfig for (%u,%s)/(%u,%s)\n",
5938             BackBufferFormat, debug_d3dformat(BackBufferFormat),
5939             StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5940     } else {
5941 #ifdef EXTRA_TRACES
5942         int i;
5943         for (i = 0; i < nCfgs; ++i) {
5944             TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5945             debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5946             debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5947         }
5948         if (NULL != This->renderTarget) {
5949             glFlush();
5950             vcheckGLcall("glFlush");
5951             /** This is only useful if the old render target was a swapchain,
5952             * we need to supercede this with a function that displays
5953             * the current buffer on the screen. This is easy to do in glx1.3 but
5954             * we need to do copy-write pixels in glx 1.2.
5955             ************************************************/
5956             glXSwapBuffers(implicitSwapChainImpl->display,
5957                            implicitSwapChainImpl->drawable);
5958             printf("Hit Enter to get next frame ...\n");
5959             getchar();
5960         }
5961 #endif
5962     }
5963 #undef PUSH1
5964 #undef PUSH2
5965
5966    return cfgs;
5967 }
5968
5969 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5970 * the functionality needs splitting up so that we don't do more than we should do.
5971 * this only seems to impact performance a little.
5972  ******************************/
5973 static HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5974                                                IWineD3DSurface *RenderSurface) {
5975
5976     /**
5977     * Currently only active for GLX >= 1.3
5978     * for others versions we'll have to use GLXPixmaps
5979     *
5980     * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5981     * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5982     * so only check OpenGL version
5983     * ..........................
5984     * I don't believe that it is a problem with NVidia headers,
5985     * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5986     * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5987     * ATI Note:
5988     * Your application will report GLX version 1.2 on glXQueryVersion.
5989     * However, it is safe to call the GLX 1.3 functions as described below.
5990     */
5991 #if defined(GL_VERSION_1_3)
5992
5993     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5994     GLXFBConfig* cfgs = NULL;
5995     IWineD3DSwapChain     *currentSwapchain;
5996     IWineD3DSwapChainImpl *currentSwapchainImpl;
5997     IWineD3DSwapChain     *implicitSwapchain;
5998     IWineD3DSwapChainImpl *implicitSwapchainImpl;
5999     IWineD3DSwapChain     *renderSurfaceSwapchain;
6000     IWineD3DSwapChainImpl *renderSurfaceSwapchainImpl;
6001
6002     /* Obtain a reference to the device implicit swapchain,
6003      * the swapchain of the current render target,
6004      * and the swapchain of the new render target.
6005      * Fallback to device implicit swapchain if the current render target doesn't have one */
6006     IWineD3DDevice_GetSwapChain(iface, 0, &implicitSwapchain);
6007     IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void**) &renderSurfaceSwapchain);
6008     IWineD3DSurface_GetContainer(This->render_targets[0], &IID_IWineD3DSwapChain, (void **)&currentSwapchain);
6009     if (currentSwapchain == NULL)
6010         IWineD3DDevice_GetSwapChain(iface, 0, &currentSwapchain);
6011
6012     currentSwapchainImpl = (IWineD3DSwapChainImpl*) currentSwapchain;
6013     implicitSwapchainImpl = (IWineD3DSwapChainImpl*) implicitSwapchain;
6014     renderSurfaceSwapchainImpl = (IWineD3DSwapChainImpl*) renderSurfaceSwapchain;
6015
6016     ENTER_GL();
6017
6018     /**
6019     * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
6020     *  renderTarget = swapchain->backBuffer[i] bit and anything to do with *glContexts
6021      **********************************************************************/
6022     if (renderSurfaceSwapchain != NULL) {
6023
6024         /* We also need to make sure that the lights &co are also in the context of the swapchains */
6025         /* FIXME: If the render target gets sent to the frontBuffer, should we be presenting it raw? */
6026         TRACE("making swapchain active\n");
6027         if (RenderSurface != This->render_targets[0]) {
6028             BOOL backbuf = FALSE;
6029             int i;
6030
6031             for(i = 0; i < renderSurfaceSwapchainImpl->presentParms.BackBufferCount; i++) {
6032                 if(RenderSurface == renderSurfaceSwapchainImpl->backBuffer[i]) {
6033                     backbuf = TRUE;
6034                     break;
6035                 }
6036             }
6037
6038             if (backbuf) {
6039             } else {
6040                 /* This could be flagged so that some operations work directly with the front buffer */
6041                 FIXME("Attempting to set the  renderTarget to the frontBuffer\n");
6042             }
6043             if (glXMakeCurrent(renderSurfaceSwapchainImpl->display,
6044                                renderSurfaceSwapchainImpl->win,
6045                                renderSurfaceSwapchainImpl->glCtx) == False) {
6046
6047                 TRACE("Error in setting current context: context %p drawable %ld !\n",
6048                        implicitSwapchainImpl->glCtx, implicitSwapchainImpl->win);
6049             }
6050             checkGLcall("glXMakeContextCurrent");
6051
6052             /* Clean up the old context */
6053             IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
6054
6055             /* Reapply the stateblock, and set the device not to render to texture */
6056             device_reapply_stateblock(This);
6057             device_render_to_texture(This, FALSE);
6058         }
6059
6060     /* Offscreen rendering: PBuffers (currently disabled).
6061      * Also note that this path is never reached if FBOs are supported */
6062     } else if (wined3d_settings.offscreen_rendering_mode == ORM_PBUFFER &&
6063                (cfgs = device_find_fbconfigs(This, implicitSwapchainImpl, RenderSurface)) != NULL) {
6064
6065         /** ********************************************************************
6066         * This is a quickly hacked out implementation of offscreen textures.
6067         * It will work in most cases but there may be problems if the client
6068         * modifies the texture directly, or expects the contents of the rendertarget
6069         * to be persistent.
6070         *
6071         * There are some real speed vs compatibility issues here:
6072         *    we should really use a new context for every texture, but that eats ram.
6073         *    we should also be restoring the texture to the pbuffer but that eats CPU
6074         *    we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
6075         *    but if this means reusing the display backbuffer then we need to make sure that
6076         *    states are correctly preserved.
6077         * In many cases I would expect that we can 'skip' some functions, such as preserving states,
6078         * and gain a good performance increase at the cost of compatibility.
6079         * I would suggest that, when this is the case, a user configurable flag be made
6080         * available, allowing the user to choose the best emulated experience for them.
6081          *********************************************************************/
6082
6083         XVisualInfo *visinfo;
6084         glContext   *newContext;
6085
6086         /* Here were using a shared context model */
6087         if (WINED3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
6088             FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6089         }
6090
6091         /* If the context doesn't exist then create a new one */
6092         /* TODO: This should really be part of findGlContext */
6093         if (NULL == newContext->context) {
6094
6095             int attribs[256];
6096             int nAttribs = 0;
6097
6098             TRACE("making new buffer\n");
6099             attribs[nAttribs++] = GLX_PBUFFER_WIDTH; 
6100             attribs[nAttribs++] = newContext->Width;
6101             attribs[nAttribs++] = GLX_PBUFFER_HEIGHT;
6102             attribs[nAttribs++] = newContext->Height;
6103             attribs[nAttribs++] = None;
6104
6105             newContext->drawable = glXCreatePbuffer(implicitSwapchainImpl->display, cfgs[0], attribs);
6106
6107             /** ****************************************
6108             *GLX1.3 isn't supported by XFree 'yet' until that point ATI emulates pBuffers
6109             *they note:
6110             *   In future releases, we may provide the calls glXCreateNewContext,
6111             *   glXQueryDrawable and glXMakeContextCurrent.
6112             *    so until then we have to use glXGetVisualFromFBConfig &co..
6113             ********************************************/
6114
6115             visinfo = glXGetVisualFromFBConfig(implicitSwapchainImpl->display, cfgs[0]);
6116             if (!visinfo) {
6117                 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
6118             } else {
6119                 newContext->context = glXCreateContext(
6120                     implicitSwapchainImpl->display, visinfo,
6121                     implicitSwapchainImpl->glCtx, GL_TRUE);
6122
6123                 XFree(visinfo);
6124             }
6125         }
6126         if (NULL == newContext || NULL == newContext->context) {
6127             ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
6128         } else {
6129             /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
6130             if (glXMakeCurrent(implicitSwapchainImpl->display,
6131                 newContext->drawable, newContext->context) == False) {
6132
6133                 TRACE("Error in setting current context: context %p drawable %ld\n",
6134                     newContext->context, newContext->drawable);
6135             }
6136             checkGLcall("glXMakeContextCurrent");
6137
6138             /* Clean up the old context */
6139             IWineD3DDeviceImpl_CleanRender(iface, currentSwapchainImpl);
6140
6141             /* Reapply stateblock, and set device to render to a texture */
6142             device_reapply_stateblock(This);
6143             device_render_to_texture(This, TRUE);
6144
6145             /* Set the current context of the swapchain to the new context */
6146             implicitSwapchainImpl->drawable   = newContext->drawable;
6147             implicitSwapchainImpl->render_ctx = newContext->context;
6148         }
6149     } else {
6150         /* Same context, but update render_offscreen and cull mode */
6151         device_render_to_texture(This, TRUE);
6152     }
6153
6154     if (cfgs != NULL)                   XFree(cfgs);
6155     if (implicitSwapchain != NULL)       IWineD3DSwapChain_Release(implicitSwapchain);
6156     if (currentSwapchain != NULL)       IWineD3DSwapChain_Release(currentSwapchain);
6157     if (renderSurfaceSwapchain != NULL) IWineD3DSwapChain_Release(renderSurfaceSwapchain);
6158     LEAVE_GL();
6159 #endif
6160     return WINED3D_OK;
6161 }
6162
6163 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
6164                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
6165     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6166     /* TODO: the use of Impl is deprecated. */
6167     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
6168
6169     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
6170
6171     /* some basic validation checks */
6172     if(This->cursorTexture) {
6173         ENTER_GL();
6174         glDeleteTextures(1, &This->cursorTexture);
6175         LEAVE_GL();
6176         This->cursorTexture = 0;
6177     }
6178
6179     if(pCursorBitmap) {
6180         /* MSDN: Cursor must be A8R8G8B8 */
6181         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
6182             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
6183             return WINED3DERR_INVALIDCALL;
6184         }
6185
6186         /* MSDN: Cursor must be smaller than the display mode */
6187         if(pSur->currentDesc.Width > This->ddraw_width ||
6188            pSur->currentDesc.Height > This->ddraw_height) {
6189             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);
6190             return WINED3DERR_INVALIDCALL;
6191         }
6192
6193         /* TODO: MSDN: Cursor sizes must be a power of 2 */
6194         /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
6195          * Texture and Blitting code to draw the cursor
6196          */
6197         pSur->Flags |= SFLAG_FORCELOAD;
6198         IWineD3DSurface_PreLoad(pCursorBitmap);
6199         pSur->Flags &= ~SFLAG_FORCELOAD;
6200         /* Do not store the surface's pointer because the application may release
6201          * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
6202          * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
6203          */
6204         This->cursorTexture = pSur->glDescription.textureName;
6205         This->cursorWidth = pSur->currentDesc.Width;
6206         This->cursorHeight = pSur->currentDesc.Height;
6207         pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
6208     }
6209
6210     This->xHotSpot = XHotSpot;
6211     This->yHotSpot = YHotSpot;
6212     return WINED3D_OK;
6213 }
6214
6215 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
6216     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6217     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
6218
6219     This->xScreenSpace = XScreenSpace;
6220     This->yScreenSpace = YScreenSpace;
6221
6222     return;
6223
6224 }
6225
6226 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
6227     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6228     BOOL oldVisible = This->bCursorVisible;
6229     TRACE("(%p) : visible(%d)\n", This, bShow);
6230
6231     if(This->cursorTexture)
6232         This->bCursorVisible = bShow;
6233
6234     return oldVisible;
6235 }
6236
6237 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
6238     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6239     TRACE("(%p) : state (%u)\n", This, This->state);
6240     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
6241     switch (This->state) {
6242     case WINED3D_OK:
6243         return WINED3D_OK;
6244     case WINED3DERR_DEVICELOST:
6245         {
6246             ResourceList *resourceList  = This->resources;
6247             while (NULL != resourceList) {
6248                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
6249                 return WINED3DERR_DEVICENOTRESET;
6250                 resourceList = resourceList->next;
6251             }
6252             return WINED3DERR_DEVICELOST;
6253         }
6254     case WINED3DERR_DRIVERINTERNALERROR:
6255         return WINED3DERR_DRIVERINTERNALERROR;
6256     }
6257
6258     /* Unknown state */
6259     return WINED3DERR_DRIVERINTERNALERROR;
6260 }
6261
6262
6263 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
6264     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6265     /** FIXME: Resource tracking needs to be done,
6266     * The closes we can do to this is set the priorities of all managed textures low
6267     * and then reset them.
6268      ***********************************************************/
6269     FIXME("(%p) : stub\n", This);
6270     return WINED3D_OK;
6271 }
6272
6273 void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6274     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
6275     if(surface->Flags & SFLAG_DIBSECTION) {
6276         /* Release the DC */
6277         SelectObject(surface->hDC, surface->dib.holdbitmap);
6278         DeleteDC(surface->hDC);
6279         /* Release the DIB section */
6280         DeleteObject(surface->dib.DIBsection);
6281         surface->dib.bitmap_data = NULL;
6282         surface->resource.allocatedMemory = NULL;
6283         surface->Flags &= ~SFLAG_DIBSECTION;
6284     }
6285     surface->currentDesc.Width = *pPresentationParameters->BackBufferWidth;
6286     surface->currentDesc.Height = *pPresentationParameters->BackBufferHeight;
6287     if (wined3d_settings.nonpower2_mode == NP2_NATIVE) {
6288         surface->pow2Width = *pPresentationParameters->BackBufferWidth;
6289         surface->pow2Height = *pPresentationParameters->BackBufferHeight;
6290     } else {
6291         surface->pow2Width = surface->pow2Height = 1;
6292         while (surface->pow2Width < *pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
6293         while (surface->pow2Height < *pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
6294     }
6295     if(surface->glDescription.textureName) {
6296         ENTER_GL();
6297         glDeleteTextures(1, &surface->glDescription.textureName);
6298         LEAVE_GL();
6299         surface->glDescription.textureName = 0;
6300     }
6301     if(surface->pow2Width != *pPresentationParameters->BackBufferWidth ||
6302        surface->pow2Height != *pPresentationParameters->BackBufferHeight) {
6303         surface->Flags |= SFLAG_NONPOW2;
6304     } else  {
6305         surface->Flags &= ~SFLAG_NONPOW2;
6306     }
6307     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
6308     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
6309 }
6310
6311 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
6312     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6313     IWineD3DSwapChainImpl *swapchain;
6314     HRESULT hr;
6315     BOOL DisplayModeChanged = FALSE;
6316     WINED3DDISPLAYMODE mode;
6317     TRACE("(%p)\n", This);
6318
6319     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
6320     if(FAILED(hr)) {
6321         ERR("Failed to get the first implicit swapchain\n");
6322         return hr;
6323     }
6324
6325     /* Is it necessary to recreate the gl context? Actually every setting can be changed
6326      * on an existing gl context, so there's no real need for recreation.
6327      *
6328      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
6329      *
6330      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
6331      */
6332     TRACE("New params:\n");
6333     TRACE("BackBufferWidth = %d\n", *pPresentationParameters->BackBufferWidth);
6334     TRACE("BackBufferHeight = %d\n", *pPresentationParameters->BackBufferHeight);
6335     TRACE("BackBufferFormat = %s\n", debug_d3dformat(*pPresentationParameters->BackBufferFormat));
6336     TRACE("BackBufferCount = %d\n", *pPresentationParameters->BackBufferCount);
6337     TRACE("MultiSampleType = %d\n", *pPresentationParameters->MultiSampleType);
6338     TRACE("MultiSampleQuality = %d\n", *pPresentationParameters->MultiSampleQuality);
6339     TRACE("SwapEffect = %d\n", *pPresentationParameters->SwapEffect);
6340     TRACE("hDeviceWindow = %p\n", *pPresentationParameters->hDeviceWindow);
6341     TRACE("Windowed = %s\n", *pPresentationParameters->Windowed ? "true" : "false");
6342     TRACE("EnableAutoDepthStencil = %s\n", *pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
6343     TRACE("Flags = %08x\n", *pPresentationParameters->Flags);
6344     TRACE("FullScreen_RefreshRateInHz = %d\n", *pPresentationParameters->FullScreen_RefreshRateInHz);
6345     TRACE("PresentationInterval = %d\n", *pPresentationParameters->PresentationInterval);
6346
6347     /* No special treatment of these parameters. Just store them */
6348     swapchain->presentParms.SwapEffect = *pPresentationParameters->SwapEffect;
6349     swapchain->presentParms.Flags = *pPresentationParameters->Flags;
6350     swapchain->presentParms.PresentationInterval = *pPresentationParameters->PresentationInterval;
6351     swapchain->presentParms.FullScreen_RefreshRateInHz = *pPresentationParameters->FullScreen_RefreshRateInHz;
6352
6353     /* What to do about these? */
6354     if(*pPresentationParameters->BackBufferCount != 0 &&
6355         *pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
6356         ERR("Cannot change the back buffer count yet\n");
6357     }
6358     if(*pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
6359         *pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
6360         ERR("Cannot change the back buffer format yet\n");
6361     }
6362     if(*pPresentationParameters->hDeviceWindow != NULL &&
6363         *pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
6364         ERR("Cannot change the device window yet\n");
6365     }
6366     if(*pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
6367         ERR("What do do about a changed auto depth stencil parameter?\n");
6368     }
6369
6370     if(*pPresentationParameters->Windowed) {
6371         mode.Width = swapchain->orig_width;
6372         mode.Height = swapchain->orig_height;
6373         mode.RefreshRate = 0;
6374         mode.Format = swapchain->presentParms.BackBufferFormat;
6375     } else {
6376         mode.Width = *pPresentationParameters->BackBufferWidth;
6377         mode.Height = *pPresentationParameters->BackBufferHeight;
6378         mode.RefreshRate = *pPresentationParameters->FullScreen_RefreshRateInHz;
6379         mode.Format = swapchain->presentParms.BackBufferFormat;
6380     }
6381
6382     /* Should Width == 800 && Height == 0 set 800x600? */
6383     if(*pPresentationParameters->BackBufferWidth != 0 && *pPresentationParameters->BackBufferHeight != 0 &&
6384        (*pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
6385         *pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
6386     {
6387         WINED3DVIEWPORT vp;
6388         int i;
6389
6390         vp.X = 0;
6391         vp.Y = 0;
6392         vp.Width = *pPresentationParameters->BackBufferWidth;
6393         vp.Height = *pPresentationParameters->BackBufferHeight;
6394         vp.MinZ = 0;
6395         vp.MaxZ = 1;
6396
6397         if(!*pPresentationParameters->Windowed) {
6398             DisplayModeChanged = TRUE;
6399         }
6400         swapchain->presentParms.BackBufferWidth = *pPresentationParameters->BackBufferWidth;
6401         swapchain->presentParms.BackBufferHeight = *pPresentationParameters->BackBufferHeight;
6402
6403         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
6404         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
6405             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
6406         }
6407
6408         /* Now set the new viewport */
6409         IWineD3DDevice_SetViewport(iface, &vp);
6410     }
6411
6412     if((*pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
6413        (swapchain->presentParms.Windowed && !*pPresentationParameters->Windowed) ||
6414         DisplayModeChanged) {
6415         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
6416     }
6417
6418     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
6419     return WINED3D_OK;
6420 }
6421
6422 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
6423     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6424     /** FIXME: always true at the moment **/
6425     if(!bEnableDialogs) {
6426         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
6427     }
6428     return WINED3D_OK;
6429 }
6430
6431
6432 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
6433     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6434     TRACE("(%p) : pParameters %p\n", This, pParameters);
6435
6436     *pParameters = This->createParms;
6437     return WINED3D_OK;
6438 }
6439
6440 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
6441     IWineD3DSwapChain *swapchain;
6442     HRESULT hrc = WINED3D_OK;
6443
6444     TRACE("Relaying  to swapchain\n");
6445
6446     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6447         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
6448         IWineD3DSwapChain_Release(swapchain);
6449     }
6450     return;
6451 }
6452
6453 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
6454     IWineD3DSwapChain *swapchain;
6455     HRESULT hrc = WINED3D_OK;
6456
6457     TRACE("Relaying  to swapchain\n");
6458
6459     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
6460         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
6461         IWineD3DSwapChain_Release(swapchain);
6462     }
6463     return;
6464 }
6465
6466
6467 /** ********************************************************
6468 *   Notification functions
6469 ** ********************************************************/
6470 /** This function must be called in the release of a resource when ref == 0,
6471 * the contents of resource must still be correct,
6472 * any handels to other resource held by the caller must be closed
6473 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
6474  *****************************************************/
6475 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6476     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6477     ResourceList* resourceList;
6478
6479     TRACE("(%p) : resource %p\n", This, resource);
6480 #if 0
6481     EnterCriticalSection(&resourceStoreCriticalSection);
6482 #endif
6483     /* add a new texture to the frot of the linked list */
6484     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
6485     resourceList->resource = resource;
6486
6487     /* Get the old head */
6488     resourceList->next = This->resources;
6489
6490     This->resources = resourceList;
6491     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
6492
6493 #if 0
6494     LeaveCriticalSection(&resourceStoreCriticalSection);
6495 #endif
6496     return;
6497 }
6498
6499 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
6500     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
6501     ResourceList* resourceList = NULL;
6502     ResourceList* previousResourceList = NULL;
6503     
6504     TRACE("(%p) : resource %p\n", This, resource);
6505
6506 #if 0
6507     EnterCriticalSection(&resourceStoreCriticalSection);
6508 #endif
6509     resourceList = This->resources;
6510
6511     while (resourceList != NULL) {
6512         if(resourceList->resource == resource) break;
6513         previousResourceList = resourceList;
6514         resourceList = resourceList->next;
6515     }
6516
6517     if (resourceList == NULL) {
6518         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
6519 #if 0
6520         LeaveCriticalSection(&resourceStoreCriticalSection);
6521 #endif
6522         return;
6523     } else {
6524             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
6525     }
6526     /* make sure we don't leave a hole in the list */
6527     if (previousResourceList != NULL) {
6528         previousResourceList->next = resourceList->next;
6529     } else {
6530         This->resources = resourceList->next;
6531     }
6532
6533 #if 0
6534     LeaveCriticalSection(&resourceStoreCriticalSection);
6535 #endif
6536     return;
6537 }
6538
6539
6540 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
6541     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
6542     int counter;
6543
6544     TRACE("(%p) : resource %p\n", This, resource);
6545     switch(IWineD3DResource_GetType(resource)){
6546         case WINED3DRTYPE_SURFACE:
6547         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
6548         break;
6549         case WINED3DRTYPE_TEXTURE:
6550         case WINED3DRTYPE_CUBETEXTURE:
6551         case WINED3DRTYPE_VOLUMETEXTURE:
6552                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
6553                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6554                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6555                         This->stateBlock->textures[counter] = NULL;
6556                     }
6557                     if (This->updateStateBlock != This->stateBlock ){
6558                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
6559                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
6560                             This->updateStateBlock->textures[counter] = NULL;
6561                         }
6562                     }
6563                 }
6564         break;
6565         case WINED3DRTYPE_VOLUME:
6566         /* TODO: nothing really? */
6567         break;
6568         case WINED3DRTYPE_VERTEXBUFFER:
6569         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
6570         {
6571             int streamNumber;
6572             TRACE("Cleaning up stream pointers\n");
6573
6574             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
6575                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
6576                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
6577                 */
6578                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6579                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
6580                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6581                         This->updateStateBlock->streamSource[streamNumber] = 0;
6582                         /* Set changed flag? */
6583                     }
6584                 }
6585                 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) */
6586                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
6587                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
6588                         This->stateBlock->streamSource[streamNumber] = 0;
6589                     }
6590                 }
6591 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
6592                  else { /* This shouldn't happen */
6593                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
6594                 }
6595 #endif
6596
6597             }
6598         }
6599         break;
6600         case WINED3DRTYPE_INDEXBUFFER:
6601         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
6602         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
6603             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6604                 This->updateStateBlock->pIndexData =  NULL;
6605             }
6606         }
6607         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
6608             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
6609                 This->stateBlock->pIndexData =  NULL;
6610             }
6611         }
6612
6613         break;
6614         default:
6615         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
6616         break;
6617     }
6618
6619
6620     /* Remove the resoruce from the resourceStore */
6621     IWineD3DDeviceImpl_RemoveResource(iface, resource);
6622
6623     TRACE("Resource released\n");
6624
6625 }
6626
6627 /**********************************************************
6628  * IWineD3DDevice VTbl follows
6629  **********************************************************/
6630
6631 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6632 {
6633     /*** IUnknown methods ***/
6634     IWineD3DDeviceImpl_QueryInterface,
6635     IWineD3DDeviceImpl_AddRef,
6636     IWineD3DDeviceImpl_Release,
6637     /*** IWineD3DDevice methods ***/
6638     IWineD3DDeviceImpl_GetParent,
6639     /*** Creation methods**/
6640     IWineD3DDeviceImpl_CreateVertexBuffer,
6641     IWineD3DDeviceImpl_CreateIndexBuffer,
6642     IWineD3DDeviceImpl_CreateStateBlock,
6643     IWineD3DDeviceImpl_CreateSurface,
6644     IWineD3DDeviceImpl_CreateTexture,
6645     IWineD3DDeviceImpl_CreateVolumeTexture,
6646     IWineD3DDeviceImpl_CreateVolume,
6647     IWineD3DDeviceImpl_CreateCubeTexture,
6648     IWineD3DDeviceImpl_CreateQuery,
6649     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6650     IWineD3DDeviceImpl_CreateVertexDeclaration,
6651     IWineD3DDeviceImpl_CreateVertexShader,
6652     IWineD3DDeviceImpl_CreatePixelShader,
6653     IWineD3DDeviceImpl_CreatePalette,
6654     /*** Odd functions **/
6655     IWineD3DDeviceImpl_Init3D,
6656     IWineD3DDeviceImpl_Uninit3D,
6657     IWineD3DDeviceImpl_SetFullscreen,
6658     IWineD3DDeviceImpl_EnumDisplayModes,
6659     IWineD3DDeviceImpl_EvictManagedResources,
6660     IWineD3DDeviceImpl_GetAvailableTextureMem,
6661     IWineD3DDeviceImpl_GetBackBuffer,
6662     IWineD3DDeviceImpl_GetCreationParameters,
6663     IWineD3DDeviceImpl_GetDeviceCaps,
6664     IWineD3DDeviceImpl_GetDirect3D,
6665     IWineD3DDeviceImpl_GetDisplayMode,
6666     IWineD3DDeviceImpl_SetDisplayMode,
6667     IWineD3DDeviceImpl_GetHWND,
6668     IWineD3DDeviceImpl_SetHWND,
6669     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6670     IWineD3DDeviceImpl_GetRasterStatus,
6671     IWineD3DDeviceImpl_GetSwapChain,
6672     IWineD3DDeviceImpl_Reset,
6673     IWineD3DDeviceImpl_SetDialogBoxMode,
6674     IWineD3DDeviceImpl_SetCursorProperties,
6675     IWineD3DDeviceImpl_SetCursorPosition,
6676     IWineD3DDeviceImpl_ShowCursor,
6677     IWineD3DDeviceImpl_TestCooperativeLevel,
6678     /*** Getters and setters **/
6679     IWineD3DDeviceImpl_SetClipPlane,
6680     IWineD3DDeviceImpl_GetClipPlane,
6681     IWineD3DDeviceImpl_SetClipStatus,
6682     IWineD3DDeviceImpl_GetClipStatus,
6683     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6684     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6685     IWineD3DDeviceImpl_SetDepthStencilSurface,
6686     IWineD3DDeviceImpl_GetDepthStencilSurface,
6687     IWineD3DDeviceImpl_SetFVF,
6688     IWineD3DDeviceImpl_GetFVF,
6689     IWineD3DDeviceImpl_SetGammaRamp,
6690     IWineD3DDeviceImpl_GetGammaRamp,
6691     IWineD3DDeviceImpl_SetIndices,
6692     IWineD3DDeviceImpl_GetIndices,
6693     IWineD3DDeviceImpl_SetBasevertexIndex,
6694     IWineD3DDeviceImpl_SetLight,
6695     IWineD3DDeviceImpl_GetLight,
6696     IWineD3DDeviceImpl_SetLightEnable,
6697     IWineD3DDeviceImpl_GetLightEnable,
6698     IWineD3DDeviceImpl_SetMaterial,
6699     IWineD3DDeviceImpl_GetMaterial,
6700     IWineD3DDeviceImpl_SetNPatchMode,
6701     IWineD3DDeviceImpl_GetNPatchMode,
6702     IWineD3DDeviceImpl_SetPaletteEntries,
6703     IWineD3DDeviceImpl_GetPaletteEntries,
6704     IWineD3DDeviceImpl_SetPixelShader,
6705     IWineD3DDeviceImpl_GetPixelShader,
6706     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6707     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6708     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6709     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6710     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6711     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6712     IWineD3DDeviceImpl_SetRenderState,
6713     IWineD3DDeviceImpl_GetRenderState,
6714     IWineD3DDeviceImpl_SetRenderTarget,
6715     IWineD3DDeviceImpl_GetRenderTarget,
6716     IWineD3DDeviceImpl_SetFrontBackBuffers,
6717     IWineD3DDeviceImpl_SetSamplerState,
6718     IWineD3DDeviceImpl_GetSamplerState,
6719     IWineD3DDeviceImpl_SetScissorRect,
6720     IWineD3DDeviceImpl_GetScissorRect,
6721     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6722     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6723     IWineD3DDeviceImpl_SetStreamSource,
6724     IWineD3DDeviceImpl_GetStreamSource,
6725     IWineD3DDeviceImpl_SetStreamSourceFreq,
6726     IWineD3DDeviceImpl_GetStreamSourceFreq,
6727     IWineD3DDeviceImpl_SetTexture,
6728     IWineD3DDeviceImpl_GetTexture,
6729     IWineD3DDeviceImpl_SetTextureStageState,
6730     IWineD3DDeviceImpl_GetTextureStageState,
6731     IWineD3DDeviceImpl_SetTransform,
6732     IWineD3DDeviceImpl_GetTransform,
6733     IWineD3DDeviceImpl_SetVertexDeclaration,
6734     IWineD3DDeviceImpl_GetVertexDeclaration,
6735     IWineD3DDeviceImpl_SetVertexShader,
6736     IWineD3DDeviceImpl_GetVertexShader,
6737     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6738     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6739     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6740     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6741     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6742     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6743     IWineD3DDeviceImpl_SetViewport,
6744     IWineD3DDeviceImpl_GetViewport,
6745     IWineD3DDeviceImpl_MultiplyTransform,
6746     IWineD3DDeviceImpl_ValidateDevice,
6747     IWineD3DDeviceImpl_ProcessVertices,
6748     /*** State block ***/
6749     IWineD3DDeviceImpl_BeginStateBlock,
6750     IWineD3DDeviceImpl_EndStateBlock,
6751     /*** Scene management ***/
6752     IWineD3DDeviceImpl_BeginScene,
6753     IWineD3DDeviceImpl_EndScene,
6754     IWineD3DDeviceImpl_Present,
6755     IWineD3DDeviceImpl_Clear,
6756     /*** Drawing ***/
6757     IWineD3DDeviceImpl_DrawPrimitive,
6758     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6759     IWineD3DDeviceImpl_DrawPrimitiveUP,
6760     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6761     IWineD3DDeviceImpl_DrawPrimitiveStrided,
6762     IWineD3DDeviceImpl_DrawRectPatch,
6763     IWineD3DDeviceImpl_DrawTriPatch,
6764     IWineD3DDeviceImpl_DeletePatch,
6765     IWineD3DDeviceImpl_ColorFill,
6766     IWineD3DDeviceImpl_UpdateTexture,
6767     IWineD3DDeviceImpl_UpdateSurface,
6768     IWineD3DDeviceImpl_GetRenderTargetData,
6769     IWineD3DDeviceImpl_GetFrontBufferData,
6770     /*** object tracking ***/
6771     IWineD3DDeviceImpl_ResourceReleased
6772 };
6773
6774
6775 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6776     WINED3DRS_ALPHABLENDENABLE   ,
6777     WINED3DRS_ALPHAFUNC          ,
6778     WINED3DRS_ALPHAREF           ,
6779     WINED3DRS_ALPHATESTENABLE    ,
6780     WINED3DRS_BLENDOP            ,
6781     WINED3DRS_COLORWRITEENABLE   ,
6782     WINED3DRS_DESTBLEND          ,
6783     WINED3DRS_DITHERENABLE       ,
6784     WINED3DRS_FILLMODE           ,
6785     WINED3DRS_FOGDENSITY         ,
6786     WINED3DRS_FOGEND             ,
6787     WINED3DRS_FOGSTART           ,
6788     WINED3DRS_LASTPIXEL          ,
6789     WINED3DRS_SHADEMODE          ,
6790     WINED3DRS_SRCBLEND           ,
6791     WINED3DRS_STENCILENABLE      ,
6792     WINED3DRS_STENCILFAIL        ,
6793     WINED3DRS_STENCILFUNC        ,
6794     WINED3DRS_STENCILMASK        ,
6795     WINED3DRS_STENCILPASS        ,
6796     WINED3DRS_STENCILREF         ,
6797     WINED3DRS_STENCILWRITEMASK   ,
6798     WINED3DRS_STENCILZFAIL       ,
6799     WINED3DRS_TEXTUREFACTOR      ,
6800     WINED3DRS_WRAP0              ,
6801     WINED3DRS_WRAP1              ,
6802     WINED3DRS_WRAP2              ,
6803     WINED3DRS_WRAP3              ,
6804     WINED3DRS_WRAP4              ,
6805     WINED3DRS_WRAP5              ,
6806     WINED3DRS_WRAP6              ,
6807     WINED3DRS_WRAP7              ,
6808     WINED3DRS_ZENABLE            ,
6809     WINED3DRS_ZFUNC              ,
6810     WINED3DRS_ZWRITEENABLE
6811 };
6812
6813 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6814     WINED3DTSS_ADDRESSW              ,
6815     WINED3DTSS_ALPHAARG0             ,
6816     WINED3DTSS_ALPHAARG1             ,
6817     WINED3DTSS_ALPHAARG2             ,
6818     WINED3DTSS_ALPHAOP               ,
6819     WINED3DTSS_BUMPENVLOFFSET        ,
6820     WINED3DTSS_BUMPENVLSCALE         ,
6821     WINED3DTSS_BUMPENVMAT00          ,
6822     WINED3DTSS_BUMPENVMAT01          ,
6823     WINED3DTSS_BUMPENVMAT10          ,
6824     WINED3DTSS_BUMPENVMAT11          ,
6825     WINED3DTSS_COLORARG0             ,
6826     WINED3DTSS_COLORARG1             ,
6827     WINED3DTSS_COLORARG2             ,
6828     WINED3DTSS_COLOROP               ,
6829     WINED3DTSS_RESULTARG             ,
6830     WINED3DTSS_TEXCOORDINDEX         ,
6831     WINED3DTSS_TEXTURETRANSFORMFLAGS
6832 };
6833
6834 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6835     WINED3DSAMP_ADDRESSU         ,
6836     WINED3DSAMP_ADDRESSV         ,
6837     WINED3DSAMP_ADDRESSW         ,
6838     WINED3DSAMP_BORDERCOLOR      ,
6839     WINED3DSAMP_MAGFILTER        ,
6840     WINED3DSAMP_MINFILTER        ,
6841     WINED3DSAMP_MIPFILTER        ,
6842     WINED3DSAMP_MIPMAPLODBIAS    ,
6843     WINED3DSAMP_MAXMIPLEVEL      ,
6844     WINED3DSAMP_MAXANISOTROPY    ,
6845     WINED3DSAMP_SRGBTEXTURE      ,
6846     WINED3DSAMP_ELEMENTINDEX
6847 };
6848
6849 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6850     WINED3DRS_AMBIENT                       ,
6851     WINED3DRS_AMBIENTMATERIALSOURCE         ,
6852     WINED3DRS_CLIPPING                      ,
6853     WINED3DRS_CLIPPLANEENABLE               ,
6854     WINED3DRS_COLORVERTEX                   ,
6855     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
6856     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
6857     WINED3DRS_FOGDENSITY                    ,
6858     WINED3DRS_FOGEND                        ,
6859     WINED3DRS_FOGSTART                      ,
6860     WINED3DRS_FOGTABLEMODE                  ,
6861     WINED3DRS_FOGVERTEXMODE                 ,
6862     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
6863     WINED3DRS_LIGHTING                      ,
6864     WINED3DRS_LOCALVIEWER                   ,
6865     WINED3DRS_MULTISAMPLEANTIALIAS          ,
6866     WINED3DRS_MULTISAMPLEMASK               ,
6867     WINED3DRS_NORMALIZENORMALS              ,
6868     WINED3DRS_PATCHEDGESTYLE                ,
6869     WINED3DRS_POINTSCALE_A                  ,
6870     WINED3DRS_POINTSCALE_B                  ,
6871     WINED3DRS_POINTSCALE_C                  ,
6872     WINED3DRS_POINTSCALEENABLE              ,
6873     WINED3DRS_POINTSIZE                     ,
6874     WINED3DRS_POINTSIZE_MAX                 ,
6875     WINED3DRS_POINTSIZE_MIN                 ,
6876     WINED3DRS_POINTSPRITEENABLE             ,
6877     WINED3DRS_RANGEFOGENABLE                ,
6878     WINED3DRS_SPECULARMATERIALSOURCE        ,
6879     WINED3DRS_TWEENFACTOR                   ,
6880     WINED3DRS_VERTEXBLEND
6881 };
6882
6883 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6884     WINED3DTSS_TEXCOORDINDEX         ,
6885     WINED3DTSS_TEXTURETRANSFORMFLAGS
6886 };
6887
6888 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6889     WINED3DSAMP_DMAPOFFSET
6890 };
6891
6892 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
6893     DWORD rep = StateTable[state].representative;
6894     DWORD idx;
6895     BYTE shift;
6896
6897     if(!rep || isStateDirty(This, rep)) return;
6898
6899     This->dirtyArray[This->numDirtyEntries++] = rep;
6900     idx = rep >> 5;
6901     shift = rep & 0x1f;
6902     This->isStateDirty[idx] |= (1 << shift);
6903 }