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