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