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