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