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