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