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