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