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