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