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