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