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