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