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