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