wined3d: Set the stream offset to 0 in DrawPrimitiveUP/DrawIndexedPrimitiveUP.
[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 Stefan Dösinger for CodeWeavers
10  * Copyright 2006-2007 Henri Verbeet
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28 #include <stdio.h>
29 #ifdef HAVE_FLOAT_H
30 # include <float.h>
31 #endif
32 #include "wined3d_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
36
37 /* Define the default light parameters as specified by MSDN */
38 const WINED3DLIGHT WINED3D_default_light = {
39
40     WINED3DLIGHT_DIRECTIONAL, /* Type */
41     { 1.0, 1.0, 1.0, 0.0 },   /* Diffuse r,g,b,a */
42     { 0.0, 0.0, 0.0, 0.0 },   /* Specular r,g,b,a */
43     { 0.0, 0.0, 0.0, 0.0 },   /* Ambient r,g,b,a, */
44     { 0.0, 0.0, 0.0 },        /* Position x,y,z */
45     { 0.0, 0.0, 1.0 },        /* Direction x,y,z */
46     0.0,                      /* Range */
47     0.0,                      /* Falloff */
48     0.0, 0.0, 0.0,            /* Attenuation 0,1,2 */
49     0.0,                      /* Theta */
50     0.0                       /* Phi */
51 };
52
53 /* x11drv GDI escapes */
54 #define X11DRV_ESCAPE 6789
55 enum x11drv_escape_codes
56 {
57     X11DRV_GET_DISPLAY,   /* get X11 display for a DC */
58     X11DRV_GET_DRAWABLE,  /* get current drawable for a DC */
59     X11DRV_GET_FONT,      /* get current X font for a DC */
60 };
61
62 /* retrieve the X display to use on a given DC */
63 static inline Display *get_display( HDC hdc )
64 {
65     Display *display;
66     enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
67
68     if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
69                     sizeof(display), (LPSTR)&display )) display = NULL;
70     return display;
71 }
72
73 /* static function declarations */
74 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
75
76 /* helper macros */
77 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
78
79 #define D3DCREATEOBJECTINSTANCE(object, type) { \
80     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
81     D3DMEMCHECK(object, pp##type); \
82     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
83     object->wineD3DDevice = This; \
84     object->parent       = parent; \
85     object->ref          = 1; \
86     *pp##type = (IWineD3D##type *) object; \
87 }
88
89 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
90     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
91     D3DMEMCHECK(object, pp##type); \
92     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
93     object->parent       = parent; \
94     object->ref          = 1; \
95     object->baseShader.device = (IWineD3DDevice*) This; \
96     list_init(&object->baseShader.linked_programs); \
97     *pp##type = (IWineD3D##type *) object; \
98 }
99
100 #define  D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
101     object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
102     D3DMEMCHECK(object, pp##type); \
103     object->lpVtbl = &IWineD3D##type##_Vtbl;  \
104     object->resource.wineD3DDevice   = This; \
105     object->resource.parent          = parent; \
106     object->resource.resourceType    = d3dtype; \
107     object->resource.ref             = 1; \
108     object->resource.pool            = Pool; \
109     object->resource.format          = Format; \
110     object->resource.usage           = Usage; \
111     object->resource.size            = _size; \
112     /* Check that we have enough video ram left */ \
113     if (Pool == WINED3DPOOL_DEFAULT) { \
114         if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
115             WARN("Out of 'bogus' video memory\n"); \
116             HeapFree(GetProcessHeap(), 0, object); \
117             *pp##type = NULL; \
118             return WINED3DERR_OUTOFVIDEOMEMORY; \
119         } \
120         globalChangeGlRam(_size); \
121     } \
122     object->resource.allocatedMemory = (0 == _size ? NULL : Pool == WINED3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
123     if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != WINED3DPOOL_DEFAULT) { \
124         FIXME("Out of memory!\n"); \
125         HeapFree(GetProcessHeap(), 0, object); \
126         *pp##type = NULL; \
127         return WINED3DERR_OUTOFVIDEOMEMORY; \
128     } \
129     *pp##type = (IWineD3D##type *) object; \
130     IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
131     TRACE("(%p) : Created resource %p\n", This, object); \
132 }
133
134 #define D3DINITIALIZEBASETEXTURE(_basetexture) { \
135     _basetexture.levels     = Levels; \
136     _basetexture.filterType = (Usage & WINED3DUSAGE_AUTOGENMIPMAP) ? WINED3DTEXF_LINEAR : WINED3DTEXF_NONE; \
137     _basetexture.LOD        = 0; \
138     _basetexture.dirty      = TRUE; \
139 }
140
141 /**********************************************************
142  * Global variable / Constants follow
143  **********************************************************/
144 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};  /* When needed for comparisons */
145
146 /**********************************************************
147  * IUnknown parts follows
148  **********************************************************/
149
150 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
151 {
152     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
153
154     TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
155     if (IsEqualGUID(riid, &IID_IUnknown)
156         || IsEqualGUID(riid, &IID_IWineD3DBase)
157         || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
158         IUnknown_AddRef(iface);
159         *ppobj = This;
160         return S_OK;
161     }
162     *ppobj = NULL;
163     return E_NOINTERFACE;
164 }
165
166 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
167     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
168     ULONG refCount = InterlockedIncrement(&This->ref);
169
170     TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
171     return refCount;
172 }
173
174 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
175     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
176     ULONG refCount = InterlockedDecrement(&This->ref);
177
178     TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
179
180     if (!refCount) {
181         if (This->fbo) {
182             GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
183         }
184         if (This->src_fbo) {
185             GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->src_fbo));
186         }
187         if (This->dst_fbo) {
188             GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->dst_fbo));
189         }
190
191         HeapFree(GetProcessHeap(), 0, This->render_targets);
192         HeapFree(GetProcessHeap(), 0, This->fbo_color_attachments);
193         HeapFree(GetProcessHeap(), 0, This->draw_buffers);
194
195         if (This->glsl_program_lookup) hash_table_destroy(This->glsl_program_lookup);
196
197         /* TODO: Clean up all the surfaces and textures! */
198         /* NOTE: You must release the parent if the object was created via a callback
199         ** ***************************/
200
201         /* Release the update stateblock */
202         if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
203             if(This->updateStateBlock != This->stateBlock)
204                 FIXME("(%p) Something's still holding the Update stateblock\n",This);
205         }
206         This->updateStateBlock = NULL;
207         { /* because were not doing proper internal refcounts releasing the primary state block
208             causes recursion with the extra checks in ResourceReleased, to avoid this we have
209             to set this->stateBlock = NULL; first */
210             IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
211             This->stateBlock = NULL;
212
213             /* Release the stateblock */
214             if(IWineD3DStateBlock_Release(stateBlock) > 0){
215                     FIXME("(%p) Something's still holding the Update stateblock\n",This);
216             }
217         }
218
219         if (This->resources != NULL ) {
220             FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
221             dumpResources(This->resources);
222         }
223
224         if(This->contexts) ERR("Context array not freed!\n");
225
226         IWineD3D_Release(This->wineD3D);
227         This->wineD3D = NULL;
228         HeapFree(GetProcessHeap(), 0, This);
229         TRACE("Freed device  %p\n", This);
230         This = NULL;
231     }
232     return refCount;
233 }
234
235 /**********************************************************
236  * IWineD3DDevice implementation follows
237  **********************************************************/
238 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
239     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
240     *pParent = This->parent;
241     IUnknown_AddRef(This->parent);
242     return WINED3D_OK;
243 }
244
245 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
246     IWineD3DDeviceImpl *This = object->resource.wineD3DDevice;  /* Needed for GL_EXTCALL */
247     GLenum error, glUsage;
248     DWORD vboUsage = object->resource.usage;
249     if(object->Flags & VBFLAG_VBOCREATEFAIL) {
250         WARN("Creating a vbo failed once, not trying again\n");
251         return;
252     }
253
254     TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p  Usage(%s)\n", object, debug_d3dusage(vboUsage));
255
256     ENTER_GL();
257     /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
258     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
259
260     /* Make sure that the gl error is cleared. Do not use checkGLcall
261       * here because checkGLcall just prints a fixme and continues. However,
262       * if an error during VBO creation occurs we can fall back to non-vbo operation
263       * with full functionality(but performance loss)
264       */
265     while(glGetError() != GL_NO_ERROR);
266
267     /* Basically the FVF parameter passed to CreateVertexBuffer is no good
268       * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
269       * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
270       * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
271       * to check if the rhw and color values are in the correct format.
272       */
273
274     GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
275     error = glGetError();
276     if(object->vbo == 0 || error != GL_NO_ERROR) {
277         WARN("Failed to create a VBO with error %d\n", error);
278         goto error;
279     }
280
281     GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
282     error = glGetError();
283     if(error != GL_NO_ERROR) {
284         WARN("Failed to bind the VBO, error %d\n", error);
285         goto error;
286     }
287
288     /* Don't use static, because dx apps tend to update the buffer
289      * quite often even if they specify 0 usage. Because we always keep the local copy
290      * we never read from the vbo and can create a write only opengl buffer.
291      */
292     switch(vboUsage & (WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC) ) {
293         case WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC:
294         case WINED3DUSAGE_DYNAMIC:
295             TRACE("Gl usage = GL_STREAM_DRAW\n");
296             glUsage = GL_STREAM_DRAW_ARB;
297             break;
298         case WINED3DUSAGE_WRITEONLY:
299         default:
300             TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
301             glUsage = GL_DYNAMIC_DRAW_ARB;
302             break;
303     }
304
305     /* Reserve memory for the buffer. The amount of data won't change
306      * so we are safe with calling glBufferData once with a NULL ptr and
307      * calling glBufferSubData on updates
308      */
309     GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
310     error = glGetError();
311     if(error != GL_NO_ERROR) {
312         WARN("glBufferDataARB failed with error %d\n", error);
313         goto error;
314     }
315
316     LEAVE_GL();
317
318     return;
319     error:
320     /* Clean up all vbo init, but continue because we can work without a vbo :-) */
321     FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
322     if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
323     object->vbo = 0;
324     object->Flags |= VBFLAG_VBOCREATEFAIL;
325     LEAVE_GL();
326     return;
327 }
328
329 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage, 
330                              DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
331                              IUnknown *parent) {
332     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
333     IWineD3DVertexBufferImpl *object;
334     WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
335     int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
336     BOOL conv;
337
338     if(Size == 0) {
339         WARN("Size 0 requested, returning WINED3DERR_INVALIDCALL\n");
340         *ppVertexBuffer = NULL;
341         return WINED3DERR_INVALIDCALL;
342     }
343
344     D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
345
346     TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
347     *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
348
349     if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
350         object->resource.allocatedMemory  = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
351     }
352     object->fvf = FVF;
353
354     /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
355      * drawStridedFast (half-life 2).
356      *
357      * Basically converting the vertices in the buffer is quite expensive, and observations
358      * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
359      * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
360      *
361      * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
362      * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
363      * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
364      * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
365      * dx7 apps.
366      * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
367      * more. In this call we can convert dx7 buffers too.
368      */
369     conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
370     if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && 
371         (dxVersion > 7 || !conv) ) {
372         CreateVBO(object);
373     }
374     return WINED3D_OK;
375 }
376
377 static void CreateIndexBufferVBO(IWineD3DDeviceImpl *This, IWineD3DIndexBufferImpl *object) {
378     GLenum error, glUsage;
379     TRACE("Creating VBO for Index Buffer %p\n", object);
380
381     /* The following code will modify the ELEMENT_ARRAY_BUFFER binding, make sure it is
382      * restored on the next draw
383      */
384     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
385
386     ENTER_GL();
387     /* Make sure that a context is there. Needed in a multithreaded environment. Otherwise this call is a nop */
388     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
389
390     while(glGetError());
391
392     GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
393     error = glGetError();
394     if(error != GL_NO_ERROR || object->vbo == 0) {
395         ERR("Creating a vbo failed, continueing without vbo for this buffer\n");
396         goto out;
397     }
398
399     GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->vbo));
400     error = glGetError();
401     if(error != GL_NO_ERROR) {
402         ERR("Failed to bind index buffer, continueing without vbo for this buffer\n");
403         goto out;
404     }
405
406     /* Use static write only usage for now. Dynamic index buffers stay in sysmem, and due to the sysmem
407         * copy no readback will be needed
408         */
409     glUsage = GL_STATIC_DRAW_ARB;
410     GL_EXTCALL(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
411     error = glGetError();
412     if(error != GL_NO_ERROR) {
413         ERR("Failed to initialize the index buffer\n");
414         goto out;
415     }
416     LEAVE_GL();
417     TRACE("Successfully created vbo %d for index buffer %p\n", object->vbo, object);
418     return;
419
420 out:
421     GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
422     GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
423     LEAVE_GL();
424     object->vbo = 0;
425 }
426
427 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage, 
428                                                     WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
429                                                     HANDLE *sharedHandle, IUnknown *parent) {
430     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
431     IWineD3DIndexBufferImpl *object;
432     TRACE("(%p) Creating index buffer\n", This);
433
434     /* Allocate the storage for the device */
435     D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
436
437     if (Pool == WINED3DPOOL_DEFAULT ) { /* We need a local copy for drawStridedSlow */
438         object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
439     }
440
441     if(Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
442         CreateIndexBufferVBO(This, object);
443     }
444
445     TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format, 
446                            debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
447     *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
448
449     return WINED3D_OK;
450 }
451
452 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
453
454     IWineD3DDeviceImpl     *This = (IWineD3DDeviceImpl *)iface;
455     IWineD3DStateBlockImpl *object;
456     int i, j;
457     HRESULT temp_result;
458
459     D3DCREATEOBJECTINSTANCE(object, StateBlock)
460     object->blockType     = Type;
461
462     for(i = 0; i < LIGHTMAP_SIZE; i++) {
463         list_init(&object->lightMap[i]);
464     }
465
466     /* Special case - Used during initialization to produce a placeholder stateblock
467           so other functions called can update a state block                         */
468     if (Type == WINED3DSBT_INIT) {
469         /* Don't bother increasing the reference count otherwise a device will never
470            be freed due to circular dependencies                                   */
471         return WINED3D_OK;
472     }
473     
474     temp_result = allocate_shader_constants(object);
475     if (WINED3D_OK != temp_result)
476         return temp_result;
477
478     /* Otherwise, might as well set the whole state block to the appropriate values  */
479     if (This->stateBlock != NULL)
480         stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
481     else
482         memset(object->streamFreq, 1, sizeof(object->streamFreq));
483
484     /* Reset the ref and type after kludging it */
485     object->wineD3DDevice = This;
486     object->ref           = 1;
487     object->blockType     = Type;
488
489     TRACE("Updating changed flags appropriate for type %d\n", Type);
490
491     if (Type == WINED3DSBT_ALL) {
492
493         TRACE("ALL => Pretend everything has changed\n");
494         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
495
496         /* Lights are not part of the changed / set structure */
497         for(j = 0; j < LIGHTMAP_SIZE; j++) {
498             struct list *e;
499             LIST_FOR_EACH(e, &object->lightMap[j]) {
500                 PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
501                 light->changed = TRUE;
502                 light->enabledChanged = TRUE;
503             }
504         }
505     } else if (Type == WINED3DSBT_PIXELSTATE) {
506
507         TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
508         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
509
510         object->changed.pixelShader = TRUE;
511
512         /* Pixel Shader Constants */
513         for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
514             object->changed.pixelShaderConstantsF[i] = TRUE;
515         for (i = 0; i < MAX_CONST_B; ++i)
516             object->changed.pixelShaderConstantsB[i] = TRUE;
517         for (i = 0; i < MAX_CONST_I; ++i)
518             object->changed.pixelShaderConstantsI[i] = TRUE;
519         
520         for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
521             object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
522         }
523         for (j = 0; j < GL_LIMITS(texture_stages); j++) {
524             for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
525                 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
526             }
527         }
528         for (j = 0 ; j < 16; j++) {
529             for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
530
531                 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
532             }
533         }
534
535     } else if (Type == WINED3DSBT_VERTEXSTATE) {
536
537         TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
538         stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
539
540         object->changed.vertexShader = TRUE;
541
542         /* Vertex Shader Constants */
543         for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
544             object->changed.vertexShaderConstantsF[i] = TRUE;
545         for (i = 0; i < MAX_CONST_B; ++i)
546             object->changed.vertexShaderConstantsB[i] = TRUE;
547         for (i = 0; i < MAX_CONST_I; ++i)
548             object->changed.vertexShaderConstantsI[i] = TRUE;
549  
550         for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
551             object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
552         }
553         for (j = 0; j < GL_LIMITS(texture_stages); j++) {
554             for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
555                 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
556             }
557         }
558         for (j = 0 ; j < 16; j++){
559             for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
560                 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
561             }
562         }
563
564         for(j = 0; j < LIGHTMAP_SIZE; j++) {
565             struct list *e;
566             LIST_FOR_EACH(e, &object->lightMap[j]) {
567                 PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
568                 light->changed = TRUE;
569                 light->enabledChanged = TRUE;
570             }
571         }
572     } else {
573         FIXME("Unrecognized state block type %d\n", Type);
574     }
575
576     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
577     return WINED3D_OK;
578 }
579
580
581 /* ************************************
582 MSDN:
583 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
584
585 Discard
586  [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise. 
587
588 If this flag is set, the contents of the depth stencil buffer will be invalid after calling either IDirect3DDevice9::Present or IDirect3DDevice9::SetDepthStencilSurface with a different depth surface.
589
590 ******************************** */
591  
592 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) {
593     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;    
594     IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
595     unsigned int pow2Width, pow2Height;
596     unsigned int Size       = 1;
597     const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
598     TRACE("(%p) Create surface\n",This);
599     
600     /** FIXME: Check ranges on the inputs are valid 
601      * MSDN
602      *   MultisampleQuality
603      *    [in] Quality level. The valid range is between zero and one less than the level
604      *    returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType. 
605      *    Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
606      *    values of paired render targets, depth stencil surfaces, and the MultiSample type
607      *    must all match.
608       *******************************/
609
610
611     /**
612     * TODO: Discard MSDN
613     * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
614     *
615     * If this flag is set, the contents of the depth stencil buffer will be
616     * invalid after calling either IDirect3DDevice9::Present or  * IDirect3DDevice9::SetDepthStencilSurface
617     * with a different depth surface.
618     *
619     *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
620     ***************************/
621
622     if(MultisampleQuality < 0) {
623         FIXME("Invalid multisample level %d\n", MultisampleQuality);
624         return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
625     }
626
627     if(MultisampleQuality > 0) {
628         FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
629         MultisampleQuality=0;
630     }
631
632     /** FIXME: Check that the format is supported
633     *    by the device.
634       *******************************/
635
636     /* Non-power2 support */
637     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
638         pow2Width = Width;
639         pow2Height = Height;
640     } else {
641         /* Find the nearest pow2 match */
642         pow2Width = pow2Height = 1;
643         while (pow2Width < Width) pow2Width <<= 1;
644         while (pow2Height < Height) pow2Height <<= 1;
645     }
646
647     if (pow2Width > Width || pow2Height > Height) {
648          /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
649         if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
650                || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
651             FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
652                     This, Width, Height);
653             return WINED3DERR_NOTAVAILABLE;
654         }
655     }
656
657     /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
658      *  it is based around 4x4 pixel blocks it requires padding, so allocate enough
659      *  space!
660       *********************************/
661     if (WINED3DFMT_UNKNOWN == Format) {
662         Size = 0;
663     } else if (Format == WINED3DFMT_DXT1) {
664         /* DXT1 is half byte per pixel */
665        Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4)) >> 1;
666
667     } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
668                Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
669        Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4));
670     } else {
671        /* The pitch is a multiple of 4 bytes */
672        Size = ((Width * tableEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
673        Size *= Height;
674     }
675
676     /** Create and initialise the surface resource **/
677     D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
678     /* "Standalone" surface */
679     IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
680
681     object->currentDesc.Width      = Width;
682     object->currentDesc.Height     = Height;
683     object->currentDesc.MultiSampleType    = MultiSample;
684     object->currentDesc.MultiSampleQuality = MultisampleQuality;
685
686     /* Setup some glformat defaults */
687     object->glDescription.glFormat         = tableEntry->glFormat;
688     object->glDescription.glFormatInternal = tableEntry->glInternal;
689     object->glDescription.glType           = tableEntry->glType;
690
691     object->glDescription.textureName      = 0;
692     object->glDescription.level            = Level;
693     object->glDescription.target           = GL_TEXTURE_2D;
694
695     /* Internal data */
696     object->pow2Width  = pow2Width;
697     object->pow2Height = pow2Height;
698
699     /* Flags */
700     object->Flags      = SFLAG_DYNLOCK;
701     object->Flags     |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
702     object->Flags     |= Discard ? SFLAG_DISCARD : 0;
703     object->Flags     |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
704     object->Flags     |= Lockable ? SFLAG_LOCKABLE : 0;
705
706
707     if (WINED3DFMT_UNKNOWN != Format) {
708         object->bytesPerPixel = tableEntry->bpp;
709     } else {
710         object->bytesPerPixel = 0;
711     }
712
713     /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
714
715     TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
716
717     /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
718     * this function is too deep to need to care about things like this.
719     * Levels need to be checked too, and possibly Type since they all affect what can be done.
720     * ****************************************/
721     switch(Pool) {
722     case WINED3DPOOL_SCRATCH:
723         if(!Lockable)
724             FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE "
725                 "which are mutually exclusive, setting lockable to TRUE\n");
726                 Lockable = TRUE;
727     break;
728     case WINED3DPOOL_SYSTEMMEM:
729         if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, "
730                                     "this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
731     case WINED3DPOOL_MANAGED:
732         if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a "
733                                                 "Usage of DYNAMIC which are mutually exclusive, not doing "
734                                                 "anything just telling you.\n");
735     break;
736     case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
737         if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
738            && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
739             WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
740     break;
741     default:
742         FIXME("(%p) Unknown pool %d\n", This, Pool);
743     break;
744     };
745
746     if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
747         FIXME("Trying to create a render target that isn't in the default pool\n");
748     }
749
750     /* mark the texture as dirty so that it gets loaded first time around*/
751     IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
752     TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
753            This, Width, Height, Format, debug_d3dformat(Format),
754            (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
755
756     /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
757     if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
758         This->ddraw_primary = (IWineD3DSurface *) object;
759
760     /* Look at the implementation and set the correct Vtable */
761     switch(Impl) {
762         case SURFACE_OPENGL:
763             /* Nothing to do, it's set already */
764             break;
765
766         case SURFACE_GDI:
767             object->lpVtbl = &IWineGDISurface_Vtbl;
768             break;
769
770         default:
771             /* To be sure to catch this */
772             ERR("Unknown requested surface implementation %d!\n", Impl);
773             IWineD3DSurface_Release((IWineD3DSurface *) object);
774             return WINED3DERR_INVALIDCALL;
775     }
776
777     list_init(&object->renderbuffers);
778
779     /* Call the private setup routine */
780     return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
781
782 }
783
784 static HRESULT  WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
785                                                  DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
786                                                  IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
787                                                  D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
788
789     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
790     IWineD3DTextureImpl *object;
791     unsigned int i;
792     UINT tmpW;
793     UINT tmpH;
794     HRESULT hr;
795     unsigned int pow2Width;
796     unsigned int pow2Height;
797
798
799     TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
800     TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
801             Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
802
803     /* TODO: It should only be possible to create textures for formats 
804              that are reported as supported */
805     if (WINED3DFMT_UNKNOWN >= Format) {
806         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
807         return WINED3DERR_INVALIDCALL;
808     }
809
810     D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
811     D3DINITIALIZEBASETEXTURE(object->baseTexture);    
812     object->width  = Width;
813     object->height = Height;
814
815     /** Non-power2 support **/
816     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
817         pow2Width = Width;
818         pow2Height = Height;
819     } else {
820         /* Find the nearest pow2 match */
821         pow2Width = pow2Height = 1;
822         while (pow2Width < Width) pow2Width <<= 1;
823         while (pow2Height < Height) pow2Height <<= 1;
824     }
825
826     /** FIXME: add support for real non-power-two if it's provided by the video card **/
827     /* Precalculated scaling for 'faked' non power of two texture coords */
828     object->pow2scalingFactorX  =  (((float)Width)  / ((float)pow2Width));
829     object->pow2scalingFactorY  =  (((float)Height) / ((float)pow2Height));
830     TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
831
832     object->baseTexture.format = Format;
833
834     /* Calculate levels for mip mapping */
835     if (Levels == 0) {
836         TRACE("calculating levels %d\n", object->baseTexture.levels);
837         object->baseTexture.levels++;
838         tmpW = Width;
839         tmpH = Height;
840         while (tmpW > 1 || tmpH > 1) {
841             tmpW = max(1, tmpW >> 1);
842             tmpH = max(1, tmpH >> 1);
843             object->baseTexture.levels++;
844         }
845         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
846     }
847
848     /* Generate all the surfaces */
849     tmpW = Width;
850     tmpH = Height;
851     for (i = 0; i < object->baseTexture.levels; i++)
852     {
853         /* use the callback to create the texture surface */
854         hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
855         if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
856             FIXME("Failed to create surface  %p\n", object);
857             /* clean up */
858             object->surfaces[i] = NULL;
859             IWineD3DTexture_Release((IWineD3DTexture *)object);
860
861             *ppTexture = NULL;
862             return hr;
863         }
864
865         IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
866         TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
867         /* calculate the next mipmap level */
868         tmpW = max(1, tmpW >> 1);
869         tmpH = max(1, tmpH >> 1);
870     }
871
872     TRACE("(%p) : Created  texture %p\n", This, object);
873     return WINED3D_OK;
874 }
875
876 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
877                                                       UINT Width, UINT Height, UINT Depth,
878                                                       UINT Levels, DWORD Usage,
879                                                       WINED3DFORMAT Format, WINED3DPOOL Pool,
880                                                       IWineD3DVolumeTexture **ppVolumeTexture,
881                                                       HANDLE *pSharedHandle, IUnknown *parent,
882                                                       D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
883
884     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
885     IWineD3DVolumeTextureImpl *object;
886     unsigned int               i;
887     UINT                       tmpW;
888     UINT                       tmpH;
889     UINT                       tmpD;
890
891     /* TODO: It should only be possible to create textures for formats 
892              that are reported as supported */
893     if (WINED3DFMT_UNKNOWN >= Format) {
894         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
895         return WINED3DERR_INVALIDCALL;
896     }
897
898     D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
899     D3DINITIALIZEBASETEXTURE(object->baseTexture);
900
901     TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
902           Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
903
904     object->width  = Width;
905     object->height = Height;
906     object->depth  = Depth;
907     object->baseTexture.format = Format;
908
909     /* Calculate levels for mip mapping */
910     if (Levels == 0) {
911         object->baseTexture.levels++;
912         tmpW = Width;
913         tmpH = Height;
914         tmpD = Depth;
915         while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
916             tmpW = max(1, tmpW >> 1);
917             tmpH = max(1, tmpH >> 1);
918             tmpD = max(1, tmpD >> 1);
919             object->baseTexture.levels++;
920         }
921         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
922     }
923
924     /* Generate all the surfaces */
925     tmpW = Width;
926     tmpH = Height;
927     tmpD = Depth;
928
929     for (i = 0; i < object->baseTexture.levels; i++)
930     {
931         HRESULT hr;
932         /* Create the volume */
933         hr = D3DCB_CreateVolume(This->parent, parent, Width, Height, Depth, Format, Pool, Usage,
934                                 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
935
936         if(FAILED(hr)) {
937             ERR("Creating a volume for the volume texture failed(%08x)\n", hr);
938             IWineD3DVolumeTexture_Release((IWineD3DVolumeTexture *) object);
939             *ppVolumeTexture = NULL;
940             return hr;
941         }
942
943         /* Set its container to this object */
944         IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
945
946         /* calcualte the next mipmap level */
947         tmpW = max(1, tmpW >> 1);
948         tmpH = max(1, tmpH >> 1);
949         tmpD = max(1, tmpD >> 1);
950     }
951
952     *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
953     TRACE("(%p) : Created volume texture %p\n", This, object);
954     return WINED3D_OK;
955 }
956
957 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
958                                                UINT Width, UINT Height, UINT Depth,
959                                                DWORD Usage,
960                                                WINED3DFORMAT Format, WINED3DPOOL Pool,
961                                                IWineD3DVolume** ppVolume,
962                                                HANDLE* pSharedHandle, IUnknown *parent) {
963
964     IWineD3DDeviceImpl        *This = (IWineD3DDeviceImpl *)iface;
965     IWineD3DVolumeImpl        *object; /** NOTE: impl ref allowed since this is a create function **/
966     const PixelFormatDesc *formatDesc  = getFormatDescEntry(Format);
967
968     D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
969
970     TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
971           Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
972
973     object->currentDesc.Width   = Width;
974     object->currentDesc.Height  = Height;
975     object->currentDesc.Depth   = Depth;
976     object->bytesPerPixel       = formatDesc->bpp;
977
978     /** Note: Volume textures cannot be dxtn, hence no need to check here **/
979     object->lockable            = TRUE;
980     object->locked              = FALSE;
981     memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
982     object->dirty               = TRUE;
983
984     return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
985 }
986
987 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
988                                                     UINT Levels, DWORD Usage,
989                                                     WINED3DFORMAT Format, WINED3DPOOL Pool,
990                                                     IWineD3DCubeTexture **ppCubeTexture,
991                                                     HANDLE *pSharedHandle, IUnknown *parent,
992                                                     D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
993
994     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
995     IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
996     unsigned int             i, j;
997     UINT                     tmpW;
998     HRESULT                  hr;
999     unsigned int pow2EdgeLength  = EdgeLength;
1000
1001     /* TODO: It should only be possible to create textures for formats 
1002              that are reported as supported */
1003     if (WINED3DFMT_UNKNOWN >= Format) {
1004         WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
1005         return WINED3DERR_INVALIDCALL;
1006     }
1007
1008     if (!GL_SUPPORT(ARB_TEXTURE_CUBE_MAP) && Pool != WINED3DPOOL_SCRATCH) {
1009         WARN("(%p) : Tried to create not supported cube texture\n", This);
1010         return WINED3DERR_INVALIDCALL;
1011     }
1012
1013     D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
1014     D3DINITIALIZEBASETEXTURE(object->baseTexture);
1015
1016     TRACE("(%p) Create Cube Texture\n", This);
1017
1018     /** Non-power2 support **/
1019
1020     /* Find the nearest pow2 match */
1021     pow2EdgeLength = 1;
1022     while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1023
1024     object->edgeLength           = EdgeLength;
1025     /* TODO: support for native non-power 2 */
1026     /* Precalculated scaling for 'faked' non power of two texture coords */
1027     object->pow2scalingFactor    = ((float)EdgeLength) / ((float)pow2EdgeLength);
1028     object->baseTexture.format = Format;
1029
1030     /* Calculate levels for mip mapping */
1031     if (Levels == 0) {
1032         object->baseTexture.levels++;
1033         tmpW = EdgeLength;
1034         while (tmpW > 1) {
1035             tmpW = max(1, tmpW >> 1);
1036             object->baseTexture.levels++;
1037         }
1038         TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1039     }
1040
1041     /* Generate all the surfaces */
1042     tmpW = EdgeLength;
1043     for (i = 0; i < object->baseTexture.levels; i++) {
1044
1045         /* Create the 6 faces */
1046         for (j = 0; j < 6; j++) {
1047
1048             hr=D3DCB_CreateSurface(This->parent, parent, tmpW, tmpW, Format, Usage, Pool,
1049                                    i /* Level */, &object->surfaces[j][i],pSharedHandle);
1050
1051             if(hr!= WINED3D_OK) {
1052                 /* clean up */
1053                 int k;
1054                 int l;
1055                 for (l = 0; l < j; l++) {
1056                     IWineD3DSurface_Release(object->surfaces[j][i]);
1057                 }
1058                 for (k = 0; k < i; k++) {
1059                     for (l = 0; l < 6; l++) {
1060                     IWineD3DSurface_Release(object->surfaces[l][j]);
1061                     }
1062                 }
1063
1064                 FIXME("(%p) Failed to create surface\n",object);
1065                 HeapFree(GetProcessHeap(),0,object);
1066                 *ppCubeTexture = NULL;
1067                 return hr;
1068             }
1069             IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1070             TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1071         }
1072         tmpW = max(1, tmpW >> 1);
1073     }
1074
1075     TRACE("(%p) : Created Cube Texture %p\n", This, object);
1076     *ppCubeTexture = (IWineD3DCubeTexture *) object;
1077     return WINED3D_OK;
1078 }
1079
1080 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1081     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1082     IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1083     HRESULT hr = WINED3DERR_NOTAVAILABLE;
1084
1085     /* Just a check to see if we support this type of query */
1086     switch(Type) {
1087     case WINED3DQUERYTYPE_OCCLUSION:
1088         TRACE("(%p) occlusion query\n", This);
1089         if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1090             hr = WINED3D_OK;
1091         else
1092             WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1093         break;
1094
1095     case WINED3DQUERYTYPE_EVENT:
1096         if(!(GL_SUPPORT(NV_FENCE) || GL_SUPPORT(APPLE_FENCE) )) {
1097             /* Half-Life 2 needs this query. It does not render the main menu correctly otherwise
1098              * Pretend to support it, faking this query does not do much harm except potentially lowering performance
1099              */
1100             FIXME("(%p) Event query: Unimplemented, but pretending to be supported\n", This);
1101         }
1102         hr = WINED3D_OK;
1103         break;
1104
1105     case WINED3DQUERYTYPE_VCACHE:
1106     case WINED3DQUERYTYPE_RESOURCEMANAGER:
1107     case WINED3DQUERYTYPE_VERTEXSTATS:
1108     case WINED3DQUERYTYPE_TIMESTAMP:
1109     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1110     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1111     case WINED3DQUERYTYPE_PIPELINETIMINGS:
1112     case WINED3DQUERYTYPE_INTERFACETIMINGS:
1113     case WINED3DQUERYTYPE_VERTEXTIMINGS:
1114     case WINED3DQUERYTYPE_PIXELTIMINGS:
1115     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1116     case WINED3DQUERYTYPE_CACHEUTILIZATION:
1117     default:
1118         FIXME("(%p) Unhandled query type %d\n", This, Type);
1119     }
1120     if(NULL == ppQuery || hr != WINED3D_OK) {
1121         return hr;
1122     }
1123
1124     D3DCREATEOBJECTINSTANCE(object, Query)
1125     object->type         = Type;
1126     /* allocated the 'extended' data based on the type of query requested */
1127     switch(Type){
1128     case WINED3DQUERYTYPE_OCCLUSION:
1129         if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1130             TRACE("(%p) Allocating data for an occlusion query\n", This);
1131             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1132             GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1133             break;
1134         }
1135     case WINED3DQUERYTYPE_EVENT:
1136         /* TODO: GL_APPLE_fence */
1137         if(GL_SUPPORT(APPLE_FENCE)) {
1138             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryEventData));
1139             GL_EXTCALL(glGenFencesAPPLE(1, &((WineQueryEventData *)(object->extendedData))->fenceId));
1140             checkGLcall("glGenFencesAPPLE");
1141         } else if(GL_SUPPORT(NV_FENCE)) {
1142             object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryEventData));
1143             GL_EXTCALL(glGenFencesNV(1, &((WineQueryEventData *)(object->extendedData))->fenceId));
1144             checkGLcall("glGenFencesNV");
1145         }
1146         break;
1147
1148     case WINED3DQUERYTYPE_VCACHE:
1149     case WINED3DQUERYTYPE_RESOURCEMANAGER:
1150     case WINED3DQUERYTYPE_VERTEXSTATS:
1151     case WINED3DQUERYTYPE_TIMESTAMP:
1152     case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1153     case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1154     case WINED3DQUERYTYPE_PIPELINETIMINGS:
1155     case WINED3DQUERYTYPE_INTERFACETIMINGS:
1156     case WINED3DQUERYTYPE_VERTEXTIMINGS:
1157     case WINED3DQUERYTYPE_PIXELTIMINGS:
1158     case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1159     case WINED3DQUERYTYPE_CACHEUTILIZATION:
1160     default:
1161         object->extendedData = 0;
1162         FIXME("(%p) Unhandled query type %d\n",This , Type);
1163     }
1164     TRACE("(%p) : Created Query %p\n", This, object);
1165     return WINED3D_OK;
1166 }
1167
1168 /*****************************************************************************
1169  * IWineD3DDeviceImpl_SetupFullscreenWindow
1170  *
1171  * Helper function that modifies a HWND's Style and ExStyle for proper
1172  * fullscreen use.
1173  *
1174  * Params:
1175  *  iface: Pointer to the IWineD3DDevice interface
1176  *  window: Window to setup
1177  *
1178  *****************************************************************************/
1179 static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *iface, HWND window) {
1180     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1181
1182     LONG style, exStyle;
1183     /* Don't do anything if an original style is stored.
1184      * That shouldn't happen
1185      */
1186     TRACE("(%p): Setting up window %p for exclusive mode\n", This, window);
1187     if (This->style || This->exStyle) {
1188         ERR("(%p): Want to change the window parameters of HWND %p, but "
1189             "another style is stored for restoration afterwards\n", This, window);
1190     }
1191
1192     /* Get the parameters and save them */
1193     style = GetWindowLongW(window, GWL_STYLE);
1194     exStyle = GetWindowLongW(window, GWL_EXSTYLE);
1195     This->style = style;
1196     This->exStyle = exStyle;
1197
1198     /* Filter out window decorations */
1199     style &= ~WS_CAPTION;
1200     style &= ~WS_THICKFRAME;
1201     exStyle &= ~WS_EX_WINDOWEDGE;
1202     exStyle &= ~WS_EX_CLIENTEDGE;
1203
1204     /* Make sure the window is managed, otherwise we won't get keyboard input */
1205     style |= WS_POPUP | WS_SYSMENU;
1206
1207     TRACE("Old style was %08x,%08x, setting to %08x,%08x\n",
1208           This->style, This->exStyle, style, exStyle);
1209
1210     SetWindowLongW(window, GWL_STYLE, style);
1211     SetWindowLongW(window, GWL_EXSTYLE, exStyle);
1212
1213     /* Inform the window about the update. */
1214     SetWindowPos(window, HWND_TOP, 0, 0,
1215             This->ddraw_width, This->ddraw_height, SWP_FRAMECHANGED);
1216     ShowWindow(window, SW_NORMAL);
1217 }
1218
1219 /*****************************************************************************
1220  * IWineD3DDeviceImpl_RestoreWindow
1221  *
1222  * Helper function that restores a windows' properties when taking it out
1223  * of fullscreen mode
1224  *
1225  * Params:
1226  *  iface: Pointer to the IWineD3DDevice interface
1227  *  window: Window to setup
1228  *
1229  *****************************************************************************/
1230 static void WINAPI IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND window) {
1231     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1232
1233     /* This could be a DDSCL_NORMAL -> DDSCL_NORMAL
1234      * switch, do nothing
1235      */
1236     if (!This->style && !This->exStyle) return;
1237
1238     TRACE("(%p): Restoring window settings of window %p to %08x, %08x\n",
1239           This, window, This->style, This->exStyle);
1240
1241     SetWindowLongW(window, GWL_STYLE, This->style);
1242     SetWindowLongW(window, GWL_EXSTYLE, This->exStyle);
1243
1244     /* Delete the old values */
1245     This->style = 0;
1246     This->exStyle = 0;
1247
1248     /* Inform the window about the update */
1249     SetWindowPos(window, 0 /* InsertAfter, ignored */,
1250                  0, 0, 0, 0, /* Pos, Size, ignored */
1251                  SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
1252 }
1253
1254 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1255 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS*  pPresentationParameters,                                                                   IWineD3DSwapChain** ppSwapChain,
1256                                                             IUnknown* parent,
1257                                                             D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1258                                                             D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1259     IWineD3DDeviceImpl      *This = (IWineD3DDeviceImpl *)iface;
1260
1261     HDC                     hDc;
1262     IWineD3DSwapChainImpl  *object; /** NOTE: impl ref allowed since this is a create function **/
1263     HRESULT                 hr = WINED3D_OK;
1264     IUnknown               *bufferParent;
1265     Display                *display;
1266
1267     TRACE("(%p) : Created Aditional Swap Chain\n", This);
1268
1269    /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1270    * does a device hold a reference to a swap chain giving them a lifetime of the device
1271    * or does the swap chain notify the device of its destruction.
1272     *******************************/
1273
1274     /* Check the params */
1275     if(pPresentationParameters->BackBufferCount > WINED3DPRESENT_BACK_BUFFER_MAX) {
1276         ERR("App requested %d back buffers, this is not supported for now\n", pPresentationParameters->BackBufferCount);
1277         return WINED3DERR_INVALIDCALL;
1278     } else if (pPresentationParameters->BackBufferCount > 1) {
1279         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");
1280     }
1281
1282     D3DCREATEOBJECTINSTANCE(object, SwapChain)
1283
1284     /*********************
1285     * Lookup the window Handle and the relating X window handle
1286     ********************/
1287
1288     /* Setup hwnd we are using, plus which display this equates to */
1289     object->win_handle = pPresentationParameters->hDeviceWindow;
1290     if (!object->win_handle) {
1291         object->win_handle = This->createParms.hFocusWindow;
1292     }
1293
1294     object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1295     if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1296         ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1297         return WINED3DERR_NOTAVAILABLE;
1298     }
1299     hDc                = GetDC(object->win_handle);
1300     display            = get_display(hDc);
1301     ReleaseDC(object->win_handle, hDc);
1302     TRACE("Using a display of %p %p\n", display, hDc);
1303
1304     if (NULL == display || NULL == hDc) {
1305         WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1306         return WINED3DERR_NOTAVAILABLE;
1307     }
1308
1309     if (object->win == 0) {
1310         WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1311         return WINED3DERR_NOTAVAILABLE;
1312     }
1313
1314     object->orig_width = GetSystemMetrics(SM_CXSCREEN);
1315     object->orig_height = GetSystemMetrics(SM_CYSCREEN);
1316     object->orig_fmt = pixelformat_for_depth(GetDeviceCaps(hDc, BITSPIXEL) * GetDeviceCaps(hDc, PLANES));
1317
1318     /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1319      *  then the corresponding dimension of the client area of the hDeviceWindow
1320      *  (or the focus window, if hDeviceWindow is NULL) is taken.
1321       **********************/
1322
1323     if (pPresentationParameters->Windowed &&
1324         ((pPresentationParameters->BackBufferWidth == 0) ||
1325          (pPresentationParameters->BackBufferHeight == 0))) {
1326
1327         RECT Rect;
1328         GetClientRect(object->win_handle, &Rect);
1329
1330         if (pPresentationParameters->BackBufferWidth == 0) {
1331            pPresentationParameters->BackBufferWidth = Rect.right;
1332            TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
1333         }
1334         if (pPresentationParameters->BackBufferHeight == 0) {
1335            pPresentationParameters->BackBufferHeight = Rect.bottom;
1336            TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
1337         }
1338     }
1339
1340     /* Put the correct figures in the presentation parameters */
1341     TRACE("Copying across presentation parameters\n");
1342     object->presentParms = *pPresentationParameters;
1343
1344     TRACE("calling rendertarget CB\n");
1345     hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1346                              parent,
1347                              object->presentParms.BackBufferWidth,
1348                              object->presentParms.BackBufferHeight,
1349                              object->presentParms.BackBufferFormat,
1350                              object->presentParms.MultiSampleType,
1351                              object->presentParms.MultiSampleQuality,
1352                              TRUE /* Lockable */,
1353                              &object->frontBuffer,
1354                              NULL /* pShared (always null)*/);
1355     if (object->frontBuffer != NULL) {
1356         IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1357     } else {
1358         ERR("Failed to create the front buffer\n");
1359         goto error;
1360     }
1361
1362     /**
1363     * Create an opengl context for the display visual
1364     *  NOTE: the visual is chosen as the window is created and the glcontext cannot
1365     *     use different properties after that point in time. FIXME: How to handle when requested format
1366     *     doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1367     *     it chooses is identical to the one already being used!
1368      **********************************/
1369     /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1370
1371     object->context = HeapAlloc(GetProcessHeap(), 0, sizeof(object->context));
1372     if(!object->context) {
1373     }
1374     object->num_contexts = 1;
1375
1376     ENTER_GL();
1377     object->context[0] = CreateContext(This, (IWineD3DSurfaceImpl *) object->frontBuffer, display, object->win);
1378     LEAVE_GL();
1379
1380     if (!object->context) {
1381         ERR("Failed to create a new context\n");
1382         hr = WINED3DERR_NOTAVAILABLE;
1383         goto error;
1384     } else {
1385         TRACE("Context created (HWND=%p, glContext=%p, Window=%ld)\n",
1386                object->win_handle, object->context[0]->glCtx, object->win);
1387     }
1388
1389    /*********************
1390    * Windowed / Fullscreen
1391    *******************/
1392
1393    /**
1394    * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1395    * so we should really check to see if there is a fullscreen swapchain already
1396    * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1397     **************************************/
1398
1399    if (!pPresentationParameters->Windowed) {
1400
1401         DEVMODEW devmode;
1402         HDC      hdc;
1403         int      bpp = 0;
1404         RECT     clip_rc;
1405
1406         /* Get info on the current display setup */
1407         hdc = GetDC(0);
1408         bpp = GetDeviceCaps(hdc, BITSPIXEL);
1409         ReleaseDC(0, hdc);
1410
1411         /* Change the display settings */
1412         memset(&devmode, 0, sizeof(DEVMODEW));
1413         devmode.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1414         devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1415         devmode.dmPelsWidth  = pPresentationParameters->BackBufferWidth;
1416         devmode.dmPelsHeight = pPresentationParameters->BackBufferHeight;
1417         MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1418         ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1419
1420         /* For GetDisplayMode */
1421         This->ddraw_width = devmode.dmPelsWidth;
1422         This->ddraw_height = devmode.dmPelsHeight;
1423         This->ddraw_format = pPresentationParameters->BackBufferFormat;
1424
1425         IWineD3DDevice_SetFullscreen(iface, TRUE);
1426
1427         /* And finally clip mouse to our screen */
1428         SetRect(&clip_rc, 0, 0, devmode.dmPelsWidth, devmode.dmPelsHeight);
1429         ClipCursor(&clip_rc);
1430     }
1431
1432    /*********************
1433    * Create the back, front and stencil buffers
1434    *******************/
1435     if(object->presentParms.BackBufferCount > 0) {
1436         int i;
1437
1438         object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1439         if(!object->backBuffer) {
1440             ERR("Out of memory\n");
1441             hr = E_OUTOFMEMORY;
1442             goto error;
1443         }
1444
1445         for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1446             TRACE("calling rendertarget CB\n");
1447             hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1448                                     parent,
1449                                     object->presentParms.BackBufferWidth,
1450                                     object->presentParms.BackBufferHeight,
1451                                     object->presentParms.BackBufferFormat,
1452                                     object->presentParms.MultiSampleType,
1453                                     object->presentParms.MultiSampleQuality,
1454                                     TRUE /* Lockable */,
1455                                     &object->backBuffer[i],
1456                                     NULL /* pShared (always null)*/);
1457             if(hr == WINED3D_OK && object->backBuffer[i]) {
1458                 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1459             } else {
1460                 ERR("Cannot create new back buffer\n");
1461                 goto error;
1462             }
1463             ENTER_GL();
1464             glDrawBuffer(GL_BACK);
1465             checkGLcall("glDrawBuffer(GL_BACK)");
1466             LEAVE_GL();
1467         }
1468     } else {
1469         object->backBuffer = NULL;
1470
1471         /* Single buffering - draw to front buffer */
1472         ENTER_GL();
1473         glDrawBuffer(GL_FRONT);
1474         checkGLcall("glDrawBuffer(GL_FRONT)");
1475         LEAVE_GL();
1476     }
1477
1478     /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1479     if (pPresentationParameters->EnableAutoDepthStencil && hr == WINED3D_OK) {
1480         TRACE("Creating depth stencil buffer\n");
1481         if (This->depthStencilBuffer == NULL ) {
1482             hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1483                                     parent,
1484                                     object->presentParms.BackBufferWidth,
1485                                     object->presentParms.BackBufferHeight,
1486                                     object->presentParms.AutoDepthStencilFormat,
1487                                     object->presentParms.MultiSampleType,
1488                                     object->presentParms.MultiSampleQuality,
1489                                     FALSE /* FIXME: Discard */,
1490                                     &This->depthStencilBuffer,
1491                                     NULL /* pShared (always null)*/  );
1492             if (This->depthStencilBuffer != NULL)
1493                 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1494         }
1495
1496         /** TODO: A check on width, height and multisample types
1497         *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1498          ****************************/
1499         object->wantsDepthStencilBuffer = TRUE;
1500     } else {
1501         object->wantsDepthStencilBuffer = FALSE;
1502     }
1503
1504     TRACE("Created swapchain %p\n", object);
1505     TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1506     return WINED3D_OK;
1507
1508 error:
1509     if (object->backBuffer) {
1510         int i;
1511         for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1512             if(object->backBuffer[i]) {
1513                 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1514                 IUnknown_Release(bufferParent); /* once for the get parent */
1515                 if (IUnknown_Release(bufferParent) > 0) {
1516                     FIXME("(%p) Something's still holding the back buffer\n",This);
1517                 }
1518             }
1519         }
1520         HeapFree(GetProcessHeap(), 0, object->backBuffer);
1521         object->backBuffer = NULL;
1522     }
1523     if(object->context) {
1524         DestroyContext(This, object->context[0]);
1525     }
1526     if(object->frontBuffer) {
1527         IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1528         IUnknown_Release(bufferParent); /* once for the get parent */
1529         if (IUnknown_Release(bufferParent) > 0) {
1530             FIXME("(%p) Something's still holding the front buffer\n",This);
1531         }
1532     }
1533     HeapFree(GetProcessHeap(), 0, object);
1534     return hr;
1535 }
1536
1537 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1538 static UINT     WINAPI  IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1539     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1540     TRACE("(%p)\n", This);
1541
1542     return This->NumberOfSwapChains;
1543 }
1544
1545 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1546     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1547     TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1548
1549     if(iSwapChain < This->NumberOfSwapChains) {
1550         *pSwapChain = This->swapchains[iSwapChain];
1551         IWineD3DSwapChain_AddRef(*pSwapChain);
1552         TRACE("(%p) returning %p\n", This, *pSwapChain);
1553         return WINED3D_OK;
1554     } else {
1555         TRACE("Swapchain out of range\n");
1556         *pSwapChain = NULL;
1557         return WINED3DERR_INVALIDCALL;
1558     }
1559 }
1560
1561 /*****
1562  * Vertex Declaration
1563  *****/
1564 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppVertexDeclaration,
1565         IUnknown *parent, const WINED3DVERTEXELEMENT *elements, size_t element_count) {
1566     IWineD3DDeviceImpl            *This   = (IWineD3DDeviceImpl *)iface;
1567     IWineD3DVertexDeclarationImpl *object = NULL;
1568     HRESULT hr = WINED3D_OK;
1569
1570     TRACE("(%p) : directXVersion %u, elements %p, element_count %d, ppDecl=%p\n",
1571             This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, elements, element_count, ppVertexDeclaration);
1572
1573     D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1574
1575     hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, elements, element_count);
1576
1577     return hr;
1578 }
1579
1580 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1581 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, IWineD3DVertexDeclaration *vertex_declaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1582     IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
1583     IWineD3DVertexShaderImpl *object;  /* NOTE: impl usage is ok, this is a create */
1584     HRESULT hr = WINED3D_OK;
1585     D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1586     object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1587
1588     TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1589
1590     if (vertex_declaration) {
1591         IWineD3DVertexShader_FakeSemantics(*ppVertexShader, vertex_declaration);
1592     }
1593
1594     hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1595
1596     if (WINED3D_OK != hr) {
1597         FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1598         IWineD3DVertexShader_Release(*ppVertexShader);
1599         return WINED3DERR_INVALIDCALL;
1600     }
1601
1602     return WINED3D_OK;
1603 }
1604
1605 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1606     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1607     IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1608     HRESULT hr = WINED3D_OK;
1609
1610     D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
1611     object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1612     hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1613     if (WINED3D_OK == hr) {
1614         TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1615     } else {
1616         WARN("(%p) : Failed to create pixel shader\n", This);
1617     }
1618
1619     return hr;
1620 }
1621
1622 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1623     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1624     IWineD3DPaletteImpl *object;
1625     HRESULT hr;
1626     TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1627
1628     /* Create the new object */
1629     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1630     if(!object) {
1631         ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1632         return E_OUTOFMEMORY;
1633     }
1634
1635     object->lpVtbl = &IWineD3DPalette_Vtbl;
1636     object->ref = 1;
1637     object->Flags = Flags;
1638     object->parent = Parent;
1639     object->wineD3DDevice = This;
1640     object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1641         
1642     object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1643
1644     if(!object->hpal) {
1645         HeapFree( GetProcessHeap(), 0, object);
1646         return E_OUTOFMEMORY;
1647     }
1648
1649     hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1650     if(FAILED(hr)) {
1651         IWineD3DPalette_Release((IWineD3DPalette *) object);
1652         return hr;
1653     }
1654
1655     *Palette = (IWineD3DPalette *) object;
1656
1657     return WINED3D_OK;
1658 }
1659
1660 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1661     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1662     IWineD3DSwapChainImpl *swapchain;
1663     DWORD state;
1664
1665     TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1666     if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1667
1668     /* TODO: Test if OpenGL is compiled in and loaded */
1669
1670     /* Initialize the texture unit mapping to a 1:1 mapping */
1671     for(state = 0; state < MAX_SAMPLERS; state++) {
1672         This->texUnitMap[state] = state;
1673     }
1674     This->oneToOneTexUnitMap = TRUE;
1675
1676     /* Setup the implicit swapchain */
1677     TRACE("Creating implicit swapchain\n");
1678     if (FAILED(D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain)) || !swapchain) {
1679         WARN("Failed to create implicit swapchain\n");
1680         return WINED3DERR_INVALIDCALL;
1681     }
1682
1683     This->NumberOfSwapChains = 1;
1684     This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1685     if(!This->swapchains) {
1686         ERR("Out of memory!\n");
1687         IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1688         return E_OUTOFMEMORY;
1689     }
1690     This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1691
1692     if(!This->ddraw_window) IWineD3DDevice_SetHWND(iface, swapchain->win_handle);
1693
1694     if(swapchain->backBuffer && swapchain->backBuffer[0]) {
1695         TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1696         This->render_targets[0] = swapchain->backBuffer[0];
1697         This->lastActiveRenderTarget = swapchain->backBuffer[0];
1698     }
1699     else {
1700         TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1701         This->render_targets[0] = swapchain->frontBuffer;
1702         This->lastActiveRenderTarget = swapchain->frontBuffer;
1703     }
1704     IWineD3DSurface_AddRef(This->render_targets[0]);
1705     This->activeContext = swapchain->context[0];
1706
1707     /* Depth Stencil support */
1708     This->stencilBufferTarget = This->depthStencilBuffer;
1709     if (NULL != This->stencilBufferTarget) {
1710         IWineD3DSurface_AddRef(This->stencilBufferTarget);
1711     }
1712
1713     /* Set up some starting GL setup */
1714     ENTER_GL();
1715     /*
1716     * Initialize openGL extension related variables
1717     *  with Default values
1718     */
1719
1720     ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps(This->wineD3D, swapchain->context[0]->display);
1721     /* Setup all the devices defaults */
1722     IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1723 #if 0
1724     IWineD3DImpl_CheckGraphicsMemory();
1725 #endif
1726
1727     { /* Set a default viewport */
1728         WINED3DVIEWPORT vp;
1729         vp.X      = 0;
1730         vp.Y      = 0;
1731         vp.Width  = pPresentationParameters->BackBufferWidth;
1732         vp.Height = pPresentationParameters->BackBufferHeight;
1733         vp.MinZ   = 0.0f;
1734         vp.MaxZ   = 1.0f;
1735         IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1736     }
1737
1738     /* Initialize the current view state */
1739     This->view_ident = 1;
1740     This->contexts[0]->last_was_rhw = 0;
1741     glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1742     checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
1743
1744     switch(wined3d_settings.offscreen_rendering_mode) {
1745         case ORM_FBO:
1746         case ORM_PBUFFER:
1747             This->offscreenBuffer = GL_BACK;
1748             break;
1749
1750         case ORM_BACKBUFFER:
1751         {
1752             if(GL_LIMITS(aux_buffers) > 0) {
1753                 TRACE("Using auxilliary buffer for offscreen rendering\n");
1754                 This->offscreenBuffer = GL_AUX0;
1755             } else {
1756                 TRACE("Using back buffer for offscreen rendering\n");
1757                 This->offscreenBuffer = GL_BACK;
1758             }
1759         }
1760     }
1761
1762     TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1763     LEAVE_GL();
1764
1765     /* Clear the screen */
1766     IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL,
1767                           WINED3DCLEAR_TARGET | pPresentationParameters->EnableAutoDepthStencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0,
1768                           0x00, 1.0, 0);
1769
1770     This->d3d_initialized = TRUE;
1771     return WINED3D_OK;
1772 }
1773
1774 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
1775     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1776     int sampler;
1777     uint i;
1778     TRACE("(%p)\n", This);
1779
1780     if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1781
1782     ENTER_GL();
1783     /* I don't think that the interface guarants that the device is destroyed from the same thread
1784      * it was created. Thus make sure a context is active for the glDelete* calls
1785      */
1786     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
1787     LEAVE_GL();
1788
1789     /* Delete the pbuffer context if there is any */
1790     if(This->pbufferContext) DestroyContext(This, This->pbufferContext);
1791
1792     /* Delete the mouse cursor texture */
1793     if(This->cursorTexture) {
1794         ENTER_GL();
1795         glDeleteTextures(1, &This->cursorTexture);
1796         LEAVE_GL();
1797         This->cursorTexture = 0;
1798     }
1799
1800     for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
1801         IWineD3DDevice_SetTexture(iface, sampler, NULL);
1802     }
1803
1804     /* Release the buffers (with sanity checks)*/
1805     TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1806     if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1807         if(This->depthStencilBuffer != This->stencilBufferTarget)
1808             FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1809     }
1810     This->stencilBufferTarget = NULL;
1811
1812     TRACE("Releasing the render target at %p\n", This->render_targets[0]);
1813     if(IWineD3DSurface_Release(This->render_targets[0]) >0){
1814           /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1815     }
1816     TRACE("Setting rendertarget to NULL\n");
1817     This->render_targets[0] = NULL;
1818
1819     if (This->depthStencilBuffer) {
1820         if(D3DCB_DestroyDepthStencilSurface(This->depthStencilBuffer) > 0) {
1821             FIXME("(%p) Something's still holding the depthStencilBuffer\n", This);
1822         }
1823         This->depthStencilBuffer = NULL;
1824     }
1825
1826     for(i=0; i < This->NumberOfSwapChains; i++) {
1827         TRACE("Releasing the implicit swapchain %d\n", i);
1828         if (D3DCB_DestroySwapChain(This->swapchains[i])  > 0) {
1829             FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1830         }
1831     }
1832
1833     HeapFree(GetProcessHeap(), 0, This->swapchains);
1834     This->swapchains = NULL;
1835     This->NumberOfSwapChains = 0;
1836
1837     This->d3d_initialized = FALSE;
1838     return WINED3D_OK;
1839 }
1840
1841 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
1842     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1843     TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
1844
1845     /* Setup the window for fullscreen mode */
1846     if(fullscreen && !This->ddraw_fullscreen) {
1847         IWineD3DDeviceImpl_SetupFullscreenWindow(iface, This->ddraw_window);
1848     } else if(!fullscreen && This->ddraw_fullscreen) {
1849         IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
1850     }
1851
1852     /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
1853      * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
1854      * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
1855      * separately.
1856      */
1857     This->ddraw_fullscreen = fullscreen;
1858 }
1859
1860 /* Enables thead safety in the wined3d device and its resources. Called by DirectDraw
1861  * from SetCooperativeLeven if DDSCL_MULTITHREADED is specified, and by d3d8/9 from
1862  * CreateDevice if D3DCREATE_MULTITHREADED is passed.
1863  *
1864  * There is no way to deactivate thread safety once it is enabled
1865  */
1866 static void WINAPI IWineD3DDeviceImpl_SetMultithreaded(IWineD3DDevice *iface) {
1867     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1868     FIXME("No thread safety in wined3d yet\n");
1869
1870     /*For now just store the flag(needed in case of ddraw) */
1871     This->createParms.BehaviorFlags |= WINED3DCREATE_MULTITHREADED;
1872
1873     return;
1874 }
1875
1876 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1877     DEVMODEW devmode;
1878     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1879     LONG ret;
1880     const PixelFormatDesc *formatDesc  = getFormatDescEntry(pMode->Format);
1881     RECT clip_rc;
1882
1883     TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1884
1885     /* Resize the screen even without a window:
1886      * The app could have unset it with SetCooperativeLevel, but not called
1887      * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1888      * but we don't have any hwnd
1889      */
1890
1891     devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1892     devmode.dmBitsPerPel = formatDesc->bpp * 8;
1893     if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
1894     devmode.dmPelsWidth  = pMode->Width;
1895     devmode.dmPelsHeight = pMode->Height;
1896
1897     devmode.dmDisplayFrequency = pMode->RefreshRate;
1898     if (pMode->RefreshRate != 0)  {
1899         devmode.dmFields |= DM_DISPLAYFREQUENCY;
1900     }
1901
1902     /* Only change the mode if necessary */
1903     if( (This->ddraw_width == pMode->Width) &&
1904         (This->ddraw_height == pMode->Height) &&
1905         (This->ddraw_format == pMode->Format) &&
1906         (pMode->RefreshRate == 0) ) {
1907         return WINED3D_OK;
1908     }
1909
1910     ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
1911     if (ret != DISP_CHANGE_SUCCESSFUL) {
1912         if(devmode.dmDisplayFrequency != 0) {
1913             WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
1914             devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
1915             devmode.dmDisplayFrequency = 0;
1916             ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
1917         }
1918         if(ret != DISP_CHANGE_SUCCESSFUL) {
1919             return DDERR_INVALIDMODE;
1920         }
1921     }
1922
1923     /* Store the new values */
1924     This->ddraw_width = pMode->Width;
1925     This->ddraw_height = pMode->Height;
1926     This->ddraw_format = pMode->Format;
1927
1928     /* Only do this with a window of course */
1929     if(This->ddraw_window)
1930       MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
1931
1932     /* And finally clip mouse to our screen */
1933     SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height);
1934     ClipCursor(&clip_rc);
1935
1936     return WINED3D_OK;
1937 }
1938
1939 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1940    IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1941    *ppD3D= This->wineD3D;
1942    TRACE("(%p) : wineD3D returning %p\n", This,  *ppD3D);
1943    IWineD3D_AddRef(*ppD3D);
1944    return WINED3D_OK;
1945 }
1946
1947 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1948     /** NOTE: There's a probably  a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
1949     * into the video ram as possible and seeing how many fit
1950     * you can also get the correct initial value from nvidia and ATI's driver via X
1951     * texture memory is video memory + AGP memory
1952     *******************/
1953     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1954     static BOOL showfixmes = TRUE;
1955     if (showfixmes) {
1956         FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
1957          (wined3d_settings.emulated_textureram/(1024*1024)),
1958          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1959          showfixmes = FALSE;
1960     }
1961     TRACE("(%p) : simulating %dMB, returning %dMB left\n",  This,
1962          (wined3d_settings.emulated_textureram/(1024*1024)),
1963          ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1964     /* return simulated texture memory left */
1965     return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1966 }
1967
1968
1969
1970 /*****
1971  * Get / Set FVF
1972  *****/
1973 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1974     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1975
1976     /* Update the current state block */
1977     This->updateStateBlock->changed.fvf      = TRUE;
1978     This->updateStateBlock->set.fvf          = TRUE;
1979
1980     if(This->updateStateBlock->fvf == fvf) {
1981         TRACE("Application is setting the old fvf over, nothing to do\n");
1982         return WINED3D_OK;
1983     }
1984
1985     This->updateStateBlock->fvf              = fvf;
1986     TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
1987     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
1988     return WINED3D_OK;
1989 }
1990
1991
1992 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1993     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1994     TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
1995     *pfvf = This->stateBlock->fvf;
1996     return WINED3D_OK;
1997 }
1998
1999 /*****
2000  * Get / Set Stream Source
2001  *****/
2002 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
2003         IWineD3DDeviceImpl       *This = (IWineD3DDeviceImpl *)iface;
2004     IWineD3DVertexBuffer     *oldSrc;
2005
2006     if (StreamNumber >= MAX_STREAMS) {
2007         WARN("Stream out of range %d\n", StreamNumber);
2008         return WINED3DERR_INVALIDCALL;
2009     }
2010
2011     oldSrc = This->stateBlock->streamSource[StreamNumber];
2012     TRACE("(%p) : StreamNo: %u, OldStream (%p), NewStream (%p), OffsetInBytes %u, NewStride %u\n", This, StreamNumber, oldSrc, pStreamData, OffsetInBytes, Stride);
2013
2014     This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
2015     This->updateStateBlock->set.streamSource[StreamNumber]     = TRUE;
2016
2017     if(oldSrc == pStreamData &&
2018        This->updateStateBlock->streamStride[StreamNumber] == Stride &&
2019        This->updateStateBlock->streamOffset[StreamNumber] == OffsetInBytes) {
2020        TRACE("Application is setting the old values over, nothing to do\n");
2021        return WINED3D_OK;
2022     }
2023
2024     This->updateStateBlock->streamSource[StreamNumber]         = pStreamData;
2025     if (pStreamData) {
2026         This->updateStateBlock->streamStride[StreamNumber]     = Stride;
2027         This->updateStateBlock->streamOffset[StreamNumber]     = OffsetInBytes;
2028     }
2029
2030     /* Handle recording of state blocks */
2031     if (This->isRecordingState) {
2032         TRACE("Recording... not performing anything\n");
2033         return WINED3D_OK;
2034     }
2035
2036     /* Need to do a getParent and pass the reffs up */
2037     /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
2038     which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
2039     so for now, just count internally   */
2040     if (pStreamData != NULL) {
2041         IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2042         InterlockedIncrement(&vbImpl->bindCount);
2043     }
2044     if (oldSrc != NULL) {
2045         InterlockedDecrement(&((IWineD3DVertexBufferImpl *) oldSrc)->bindCount);
2046     }
2047
2048     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2049
2050     return WINED3D_OK;
2051 }
2052
2053 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2054     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2055
2056     TRACE("(%p) : StreamNo: %u, Stream (%p), Offset %u, Stride %u\n", This, StreamNumber,
2057            This->stateBlock->streamSource[StreamNumber],
2058            This->stateBlock->streamOffset[StreamNumber],
2059            This->stateBlock->streamStride[StreamNumber]);
2060
2061     if (StreamNumber >= MAX_STREAMS) {
2062         WARN("Stream out of range %d\n", StreamNumber);
2063         return WINED3DERR_INVALIDCALL;
2064     }
2065     *pStream = This->stateBlock->streamSource[StreamNumber];
2066     *pStride = This->stateBlock->streamStride[StreamNumber];
2067     if (pOffset) {
2068         *pOffset = This->stateBlock->streamOffset[StreamNumber];
2069     }
2070
2071     if (*pStream != NULL) {
2072         IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2073     }
2074     return WINED3D_OK;
2075 }
2076
2077 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT Divider) {
2078     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2079     UINT oldFlags = This->updateStateBlock->streamFlags[StreamNumber];
2080     UINT oldFreq = This->updateStateBlock->streamFreq[StreamNumber];
2081
2082     TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2083     This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA  | WINED3DSTREAMSOURCE_INDEXEDDATA );
2084
2085     This->updateStateBlock->changed.streamFreq[StreamNumber]  = TRUE;
2086     This->updateStateBlock->set.streamFreq[StreamNumber]      = TRUE;
2087     This->updateStateBlock->streamFreq[StreamNumber]          = Divider & 0x7FFFFF;
2088
2089     if(This->updateStateBlock->streamFreq[StreamNumber] != oldFreq ||
2090        This->updateStateBlock->streamFlags[StreamNumber] != oldFlags) {
2091         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2092     }
2093
2094     return WINED3D_OK;
2095 }
2096
2097 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface,  UINT StreamNumber, UINT* Divider) {
2098     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2099
2100     TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2101     *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2102
2103     TRACE("(%p) : returning %d\n", This, *Divider);
2104
2105     return WINED3D_OK;
2106 }
2107
2108 /*****
2109  * Get / Set & Multiply Transform
2110  *****/
2111 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2112     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2113
2114     /* Most of this routine, comments included copied from ddraw tree initially: */
2115     TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2116
2117     /* Handle recording of state blocks */
2118     if (This->isRecordingState) {
2119         TRACE("Recording... not performing anything\n");
2120         This->updateStateBlock->changed.transform[d3dts] = TRUE;
2121         This->updateStateBlock->set.transform[d3dts]     = TRUE;
2122         memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2123         return WINED3D_OK;
2124     }
2125
2126     /*
2127      * If the new matrix is the same as the current one,
2128      * we cut off any further processing. this seems to be a reasonable
2129      * optimization because as was noticed, some apps (warcraft3 for example)
2130      * tend towards setting the same matrix repeatedly for some reason.
2131      *
2132      * From here on we assume that the new matrix is different, wherever it matters.
2133      */
2134     if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2135         TRACE("The app is setting the same matrix over again\n");
2136         return WINED3D_OK;
2137     } else {
2138         conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2139     }
2140
2141     /*
2142        ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2143        where ViewMat = Camera space, WorldMat = world space.
2144
2145        In OpenGL, camera and world space is combined into GL_MODELVIEW
2146        matrix.  The Projection matrix stay projection matrix.
2147      */
2148
2149     /* Capture the times we can just ignore the change for now */
2150     if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2151         This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2152         /* Handled by the state manager */
2153     }
2154
2155     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2156     return WINED3D_OK;
2157
2158 }
2159 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2160     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2161     TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2162     memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2163     return WINED3D_OK;
2164 }
2165
2166 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2167     WINED3DMATRIX *mat = NULL;
2168     WINED3DMATRIX temp;
2169
2170     /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2171      * below means it will be recorded in a state block change, but it
2172      * works regardless where it is recorded.
2173      * If this is found to be wrong, change to StateBlock.
2174      */
2175     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2176     TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2177
2178     if (State < HIGHEST_TRANSFORMSTATE)
2179     {
2180         mat = &This->updateStateBlock->transforms[State];
2181     } else {
2182         FIXME("Unhandled transform state!!\n");
2183     }
2184
2185     multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2186
2187     /* Apply change via set transform - will reapply to eg. lights this way */
2188     return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2189 }
2190
2191 /*****
2192  * Get / Set Light
2193  *****/
2194 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2195    you can reference any indexes you want as long as that number max are enabled at any
2196    one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2197    However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2198    but when recording, just build a chain pretty much of commands to be replayed.                  */
2199
2200 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2201     float rho;
2202     PLIGHTINFOEL *object = NULL;
2203     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2204     struct list *e;
2205
2206     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2207     TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This, Index, pLight, Hi);
2208
2209     /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2210      * the gl driver.
2211      */
2212     if(!pLight) {
2213         WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2214         return WINED3DERR_INVALIDCALL;
2215     }
2216
2217     switch(pLight->Type) {
2218         case WINED3DLIGHT_POINT:
2219         case WINED3DLIGHT_SPOT:
2220         case WINED3DLIGHT_PARALLELPOINT:
2221         case WINED3DLIGHT_GLSPOT:
2222             /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2223              * most wanted
2224              */
2225             if(pLight->Attenuation0 < 0.0 || pLight->Attenuation1 < 0.0 || pLight->Attenuation2 < 0.0) {
2226                 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2227                 return WINED3DERR_INVALIDCALL;
2228             }
2229             break;
2230
2231         case WINED3DLIGHT_DIRECTIONAL:
2232             /* Ignores attenuation */
2233             break;
2234
2235         default:
2236         WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2237         return WINED3DERR_INVALIDCALL;
2238     }
2239
2240     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2241         object = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2242         if(object->OriginalIndex == Index) break;
2243         object = NULL;
2244     }
2245
2246     if(!object) {
2247         TRACE("Adding new light\n");
2248         object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2249         if(!object) {
2250             ERR("Out of memory error when allocating a light\n");
2251             return E_OUTOFMEMORY;
2252         }
2253         list_add_head(&This->updateStateBlock->lightMap[Hi], &object->entry);
2254         object->glIndex = -1;
2255         object->OriginalIndex = Index;
2256         object->changed = TRUE;
2257     }
2258
2259     /* Initialize the object */
2260     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,
2261           pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2262           pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2263           pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2264     TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2265           pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2266     TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2267
2268     /* Save away the information */
2269     memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2270
2271     switch (pLight->Type) {
2272     case WINED3DLIGHT_POINT:
2273         /* Position */
2274         object->lightPosn[0] = pLight->Position.x;
2275         object->lightPosn[1] = pLight->Position.y;
2276         object->lightPosn[2] = pLight->Position.z;
2277         object->lightPosn[3] = 1.0f;
2278         object->cutoff = 180.0f;
2279         /* FIXME: Range */
2280         break;
2281
2282     case WINED3DLIGHT_DIRECTIONAL:
2283         /* Direction */
2284         object->lightPosn[0] = -pLight->Direction.x;
2285         object->lightPosn[1] = -pLight->Direction.y;
2286         object->lightPosn[2] = -pLight->Direction.z;
2287         object->lightPosn[3] = 0.0;
2288         object->exponent     = 0.0f;
2289         object->cutoff       = 180.0f;
2290         break;
2291
2292     case WINED3DLIGHT_SPOT:
2293         /* Position */
2294         object->lightPosn[0] = pLight->Position.x;
2295         object->lightPosn[1] = pLight->Position.y;
2296         object->lightPosn[2] = pLight->Position.z;
2297         object->lightPosn[3] = 1.0;
2298
2299         /* Direction */
2300         object->lightDirn[0] = pLight->Direction.x;
2301         object->lightDirn[1] = pLight->Direction.y;
2302         object->lightDirn[2] = pLight->Direction.z;
2303         object->lightDirn[3] = 1.0;
2304
2305         /*
2306          * opengl-ish and d3d-ish spot lights use too different models for the
2307          * light "intensity" as a function of the angle towards the main light direction,
2308          * so we only can approximate very roughly.
2309          * however spot lights are rather rarely used in games (if ever used at all).
2310          * furthermore if still used, probably nobody pays attention to such details.
2311          */
2312         if (pLight->Falloff == 0) {
2313             rho = 6.28f;
2314         } else {
2315             rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2316         }
2317         if (rho < 0.0001) rho = 0.0001f;
2318         object->exponent = -0.3/log(cos(rho/2));
2319         if (object->exponent > 128.0) {
2320                 object->exponent = 128.0;
2321         }
2322         object->cutoff = pLight->Phi*90/M_PI;
2323
2324         /* FIXME: Range */
2325         break;
2326
2327     default:
2328         FIXME("Unrecognized light type %d\n", pLight->Type);
2329     }
2330
2331     /* Update the live definitions if the light is currently assigned a glIndex */
2332     if (object->glIndex != -1 && !This->isRecordingState) {
2333         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(object->glIndex));
2334     }
2335     return WINED3D_OK;
2336 }
2337
2338 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2339     PLIGHTINFOEL *lightInfo = NULL;
2340     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2341     DWORD Hi = LIGHTMAP_HASHFUNC(Index);
2342     struct list *e;
2343     TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2344
2345     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2346         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2347         if(lightInfo->OriginalIndex == Index) break;
2348         lightInfo = NULL;
2349     }
2350
2351     if (lightInfo == NULL) {
2352         TRACE("Light information requested but light not defined\n");
2353         return WINED3DERR_INVALIDCALL;
2354     }
2355
2356     memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2357     return WINED3D_OK;
2358 }
2359
2360 /*****
2361  * Get / Set Light Enable
2362  *   (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2363  *****/
2364 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2365     PLIGHTINFOEL *lightInfo = NULL;
2366     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2367     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2368     struct list *e;
2369     TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2370
2371     /* Tests show true = 128...not clear why */
2372     Enable = Enable? 128: 0;
2373
2374     LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2375         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2376         if(lightInfo->OriginalIndex == Index) break;
2377         lightInfo = NULL;
2378     }
2379     TRACE("Found light: %p\n", lightInfo);
2380
2381     /* Special case - enabling an undefined light creates one with a strict set of parms! */
2382     if (lightInfo == NULL) {
2383
2384         TRACE("Light enabled requested but light not defined, so defining one!\n");
2385         IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2386
2387         /* Search for it again! Should be fairly quick as near head of list */
2388         LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2389             lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2390             if(lightInfo->OriginalIndex == Index) break;
2391             lightInfo = NULL;
2392         }
2393         if (lightInfo == NULL) {
2394             FIXME("Adding default lights has failed dismally\n");
2395             return WINED3DERR_INVALIDCALL;
2396         }
2397     }
2398
2399     lightInfo->enabledChanged = TRUE;
2400     if(!Enable) {
2401         if(lightInfo->glIndex != -1) {
2402             if(!This->isRecordingState) {
2403                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(lightInfo->glIndex));
2404             }
2405
2406             This->stateBlock->activeLights[lightInfo->glIndex] = NULL;
2407             lightInfo->glIndex = -1;
2408         } else {
2409             TRACE("Light already disabled, nothing to do\n");
2410         }
2411     } else {
2412         if (lightInfo->glIndex != -1) {
2413             /* nop */
2414             TRACE("Nothing to do as light was enabled\n");
2415         } else {
2416             int i;
2417             /* Find a free gl light */
2418             for(i = 0; i < This->maxConcurrentLights; i++) {
2419                 if(This->stateBlock->activeLights[i] == NULL) {
2420                     This->stateBlock->activeLights[i] = lightInfo;
2421                     lightInfo->glIndex = i;
2422                     break;
2423                 }
2424             }
2425             if(lightInfo->glIndex == -1) {
2426                 ERR("Too many concurrently active lights\n");
2427                 return WINED3DERR_INVALIDCALL;
2428             }
2429
2430             /* i == lightInfo->glIndex */
2431             if(!This->isRecordingState) {
2432                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(i));
2433             }
2434         }
2435     }
2436
2437     return WINED3D_OK;
2438 }
2439
2440 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2441
2442     PLIGHTINFOEL *lightInfo = NULL;
2443     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2444     struct list *e;
2445     UINT Hi = LIGHTMAP_HASHFUNC(Index);
2446     TRACE("(%p) : for idx(%d)\n", This, Index);
2447
2448     LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2449         lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2450         if(lightInfo->OriginalIndex == Index) break;
2451         lightInfo = NULL;
2452     }
2453
2454     if (lightInfo == NULL) {
2455         TRACE("Light enabled state requested but light not defined\n");
2456         return WINED3DERR_INVALIDCALL;
2457     }
2458     /* true is 128 according to SetLightEnable */
2459     *pEnable = lightInfo->glIndex != -1 ? 128 : 0;
2460     return WINED3D_OK;
2461 }
2462
2463 /*****
2464  * Get / Set Clip Planes
2465  *****/
2466 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2467     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2468     TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
2469
2470     /* Validate Index */
2471     if (Index >= GL_LIMITS(clipplanes)) {
2472         TRACE("Application has requested clipplane this device doesn't support\n");
2473         return WINED3DERR_INVALIDCALL;
2474     }
2475
2476     This->updateStateBlock->changed.clipplane[Index] = TRUE;
2477     This->updateStateBlock->set.clipplane[Index] = TRUE;
2478
2479     if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] &&
2480        This->updateStateBlock->clipplane[Index][1] == pPlane[1] &&
2481        This->updateStateBlock->clipplane[Index][2] == pPlane[2] &&
2482        This->updateStateBlock->clipplane[Index][3] == pPlane[3]) {
2483         TRACE("Application is setting old values over, nothing to do\n");
2484         return WINED3D_OK;
2485     }
2486
2487     This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2488     This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2489     This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2490     This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2491
2492     /* Handle recording of state blocks */
2493     if (This->isRecordingState) {
2494         TRACE("Recording... not performing anything\n");
2495         return WINED3D_OK;
2496     }
2497
2498     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_CLIPPLANE(Index));
2499
2500     return WINED3D_OK;
2501 }
2502
2503 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2504     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2505     TRACE("(%p) : for idx %d\n", This, Index);
2506
2507     /* Validate Index */
2508     if (Index >= GL_LIMITS(clipplanes)) {
2509         TRACE("Application has requested clipplane this device doesn't support\n");
2510         return WINED3DERR_INVALIDCALL;
2511     }
2512
2513     pPlane[0] = This->stateBlock->clipplane[Index][0];
2514     pPlane[1] = This->stateBlock->clipplane[Index][1];
2515     pPlane[2] = This->stateBlock->clipplane[Index][2];
2516     pPlane[3] = This->stateBlock->clipplane[Index][3];
2517     return WINED3D_OK;
2518 }
2519
2520 /*****
2521  * Get / Set Clip Plane Status
2522  *   WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2523  *****/
2524 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2525     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2526     FIXME("(%p) : stub\n", This);
2527     if (NULL == pClipStatus) {
2528       return WINED3DERR_INVALIDCALL;
2529     }
2530     This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2531     This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2532     return WINED3D_OK;
2533 }
2534
2535 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2536     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2537     FIXME("(%p) : stub\n", This);
2538     if (NULL == pClipStatus) {
2539       return WINED3DERR_INVALIDCALL;
2540     }
2541     pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2542     pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2543     return WINED3D_OK;
2544 }
2545
2546 /*****
2547  * Get / Set Material
2548  *****/
2549 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2550     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2551
2552     This->updateStateBlock->changed.material = TRUE;
2553     This->updateStateBlock->set.material = TRUE;
2554     memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2555
2556     /* Handle recording of state blocks */
2557     if (This->isRecordingState) {
2558         TRACE("Recording... not performing anything\n");
2559         return WINED3D_OK;
2560     }
2561
2562     ENTER_GL();
2563     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2564         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2565     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2566         pMaterial->Ambient.b, pMaterial->Ambient.a);
2567     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2568         pMaterial->Specular.b, pMaterial->Specular.a);
2569     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2570         pMaterial->Emissive.b, pMaterial->Emissive.a);
2571     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2572
2573     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2574     checkGLcall("glMaterialfv(GL_AMBIENT)");
2575     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2576     checkGLcall("glMaterialfv(GL_DIFFUSE)");
2577
2578     /* Only change material color if specular is enabled, otherwise it is set to black */
2579     if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2580        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2581        checkGLcall("glMaterialfv(GL_SPECULAR");
2582     } else {
2583        float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2584        glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2585        checkGLcall("glMaterialfv(GL_SPECULAR");
2586     }
2587     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2588     checkGLcall("glMaterialfv(GL_EMISSION)");
2589     glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2590     checkGLcall("glMaterialf(GL_SHININESS");
2591
2592     LEAVE_GL();
2593     return WINED3D_OK;
2594 }
2595
2596 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2597     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2598     memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2599     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2600         pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2601     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2602         pMaterial->Ambient.b, pMaterial->Ambient.a);
2603     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2604         pMaterial->Specular.b, pMaterial->Specular.a);
2605     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2606         pMaterial->Emissive.b, pMaterial->Emissive.a);
2607     TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2608
2609     return WINED3D_OK;
2610 }
2611
2612 /*****
2613  * Get / Set Indices
2614  *****/
2615 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2616                                              UINT BaseVertexIndex) {
2617     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
2618     IWineD3DIndexBuffer *oldIdxs;
2619     UINT oldBaseIndex = This->updateStateBlock->baseVertexIndex;
2620
2621     TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2622     oldIdxs = This->updateStateBlock->pIndexData;
2623
2624     This->updateStateBlock->changed.indices = TRUE;
2625     This->updateStateBlock->set.indices = TRUE;
2626     This->updateStateBlock->pIndexData = pIndexData;
2627     This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2628
2629     /* Handle recording of state blocks */
2630     if (This->isRecordingState) {
2631         TRACE("Recording... not performing anything\n");
2632         return WINED3D_OK;
2633     }
2634
2635     /* The base vertex index affects the stream sources, while
2636      * The index buffer is a seperate index buffer state
2637      */
2638     if(BaseVertexIndex != oldBaseIndex) {
2639         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2640     }
2641     if(oldIdxs != pIndexData) {
2642         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
2643     }
2644     return WINED3D_OK;
2645 }
2646
2647 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2648     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2649
2650     *ppIndexData = This->stateBlock->pIndexData;
2651
2652     /* up ref count on ppindexdata */
2653     if (*ppIndexData) {
2654         IWineD3DIndexBuffer_AddRef(*ppIndexData);
2655         *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2656         TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2657     }else{
2658         TRACE("(%p) No index data set\n", This);
2659     }
2660     TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2661
2662     return WINED3D_OK;
2663 }
2664
2665 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
2666 static HRESULT WINAPI IWineD3DDeviceImpl_SetBasevertexIndex(IWineD3DDevice *iface, UINT BaseIndex) {
2667     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2668     TRACE("(%p)->(%d)\n", This, BaseIndex);
2669
2670     if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
2671         TRACE("Application is setting the old value over, nothing to do\n");
2672         return WINED3D_OK;
2673     }
2674
2675     This->updateStateBlock->baseVertexIndex = BaseIndex;
2676
2677     if (This->isRecordingState) {
2678         TRACE("Recording... not performing anything\n");
2679         return WINED3D_OK;
2680     }
2681     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2682     return WINED3D_OK;
2683 }
2684
2685 /*****
2686  * Get / Set Viewports
2687  *****/
2688 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2689     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2690
2691     TRACE("(%p)\n", This);
2692     This->updateStateBlock->changed.viewport = TRUE;
2693     This->updateStateBlock->set.viewport = TRUE;
2694     memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2695
2696     /* Handle recording of state blocks */
2697     if (This->isRecordingState) {
2698         TRACE("Recording... not performing anything\n");
2699         return WINED3D_OK;
2700     }
2701
2702     TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
2703           pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2704
2705     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
2706     return WINED3D_OK;
2707
2708 }
2709
2710 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2711     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2712     TRACE("(%p)\n", This);
2713     memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2714     return WINED3D_OK;
2715 }
2716
2717 /*****
2718  * Get / Set Render States
2719  * TODO: Verify against dx9 definitions
2720  *****/
2721 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
2722
2723     IWineD3DDeviceImpl  *This     = (IWineD3DDeviceImpl *)iface;
2724     DWORD oldValue = This->stateBlock->renderState[State];
2725
2726     TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
2727
2728     This->updateStateBlock->changed.renderState[State] = TRUE;
2729     This->updateStateBlock->set.renderState[State] = TRUE;
2730     This->updateStateBlock->renderState[State] = Value;
2731
2732     /* Handle recording of state blocks */
2733     if (This->isRecordingState) {
2734         TRACE("Recording... not performing anything\n");
2735         return WINED3D_OK;
2736     }
2737
2738     /* Compared here and not before the assignment to allow proper stateblock recording */
2739     if(Value == oldValue) {
2740         TRACE("Application is setting the old value over, nothing to do\n");
2741     } else {
2742         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
2743     }
2744
2745     return WINED3D_OK;
2746 }
2747
2748 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
2749     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2750     TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
2751     *pValue = This->stateBlock->renderState[State];
2752     return WINED3D_OK;
2753 }
2754
2755 /*****
2756  * Get / Set Sampler States
2757  * TODO: Verify against dx9 definitions
2758  *****/
2759
2760 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
2761     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2762     DWORD oldValue = This->stateBlock->samplerState[Sampler][Type];
2763
2764     /**
2765     * SetSampler is designed to allow for more than the standard up to 8 textures
2766     *  and Geforce has stopped supporting more than 6 standard textures in openGL.
2767     * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
2768     *
2769     * http://developer.nvidia.com/object/General_FAQ.html#t6
2770     *
2771     * There are two new settings for GForce
2772     * the sampler one:
2773     * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
2774     * and the texture one:
2775     * GL_MAX_TEXTURE_COORDS_ARB.
2776     * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
2777      ******************/
2778
2779     TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
2780         debug_d3dsamplerstate(Type), Type, Value);
2781     This->updateStateBlock->samplerState[Sampler][Type]         = Value;
2782     This->updateStateBlock->set.samplerState[Sampler][Type]     = Value;
2783     This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
2784
2785     /* Handle recording of state blocks */
2786     if (This->isRecordingState) {
2787         TRACE("Recording... not performing anything\n");
2788         return WINED3D_OK;
2789     }
2790
2791     if(oldValue == Value) {
2792         TRACE("Application is setting the old value over, nothing to do\n");
2793         return WINED3D_OK;
2794     }
2795
2796     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
2797
2798     return WINED3D_OK;
2799 }
2800
2801 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
2802     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2803     *Value = This->stateBlock->samplerState[Sampler][Type];
2804     TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
2805
2806     return WINED3D_OK;
2807 }
2808
2809 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
2810     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2811
2812     This->updateStateBlock->set.scissorRect = TRUE;
2813     This->updateStateBlock->changed.scissorRect = TRUE;
2814     if(EqualRect(&This->updateStateBlock->scissorRect, pRect)) {
2815         TRACE("App is setting the old scissor rectangle over, nothing to do\n");
2816         return WINED3D_OK;
2817     }
2818     CopyRect(&This->updateStateBlock->scissorRect, pRect);
2819
2820     if(This->isRecordingState) {
2821         TRACE("Recording... not performing anything\n");
2822         return WINED3D_OK;
2823     }
2824
2825     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
2826
2827     return WINED3D_OK;
2828 }
2829
2830 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
2831     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2832
2833     memcpy(pRect, &This->updateStateBlock->scissorRect, sizeof(pRect));
2834     TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2835     return WINED3D_OK;
2836 }
2837
2838 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
2839     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2840     IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
2841
2842     TRACE("(%p) : pDecl=%p\n", This, pDecl);
2843
2844     This->updateStateBlock->vertexDecl = pDecl;
2845     This->updateStateBlock->changed.vertexDecl = TRUE;
2846     This->updateStateBlock->set.vertexDecl = TRUE;
2847
2848     if (This->isRecordingState) {
2849         TRACE("Recording... not performing anything\n");
2850         return WINED3D_OK;
2851     } else if(pDecl == oldDecl) {
2852         /* Checked after the assignment to allow proper stateblock recording */
2853         TRACE("Application is setting the old declaration over, nothing to do\n");
2854         return WINED3D_OK;
2855     }
2856
2857     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
2858     return WINED3D_OK;
2859 }
2860
2861 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
2862     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2863
2864     TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
2865
2866     *ppDecl = This->stateBlock->vertexDecl;
2867     if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
2868     return WINED3D_OK;
2869 }
2870
2871 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
2872     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
2873     IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
2874
2875     This->updateStateBlock->vertexShader         = pShader;
2876     This->updateStateBlock->changed.vertexShader = TRUE;
2877     This->updateStateBlock->set.vertexShader     = TRUE;
2878
2879     if (This->isRecordingState) {
2880         TRACE("Recording... not performing anything\n");
2881         return WINED3D_OK;
2882     } else if(oldShader == pShader) {
2883         /* Checked here to allow proper stateblock recording */
2884         TRACE("App is setting the old shader over, nothing to do\n");
2885         return WINED3D_OK;
2886     }
2887
2888     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
2889
2890     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
2891
2892     return WINED3D_OK;
2893 }
2894
2895 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
2896     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2897
2898     if (NULL == ppShader) {
2899         return WINED3DERR_INVALIDCALL;
2900     }
2901     *ppShader = This->stateBlock->vertexShader;
2902     if( NULL != *ppShader)
2903         IWineD3DVertexShader_AddRef(*ppShader);
2904
2905     TRACE("(%p) : returning %p\n", This, *ppShader);
2906     return WINED3D_OK;
2907 }
2908
2909 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
2910     IWineD3DDevice *iface,
2911     UINT start,
2912     CONST BOOL *srcData,
2913     UINT count) {
2914
2915     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2916     int i, cnt = min(count, MAX_CONST_B - start);
2917
2918     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2919             iface, srcData, start, count);
2920
2921     if (srcData == NULL || cnt < 0)
2922         return WINED3DERR_INVALIDCALL;
2923
2924     memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
2925     for (i = 0; i < cnt; i++)
2926         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
2927
2928     for (i = start; i < cnt + start; ++i) {
2929         This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
2930         This->updateStateBlock->set.vertexShaderConstantsB[i]     = TRUE;
2931     }
2932
2933     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
2934
2935     return WINED3D_OK;
2936 }
2937
2938 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
2939     IWineD3DDevice *iface,
2940     UINT start,
2941     BOOL *dstData,
2942     UINT count) {
2943
2944     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2945     int cnt = min(count, MAX_CONST_B - start);
2946
2947     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2948             iface, dstData, start, count);
2949
2950     if (dstData == NULL || cnt < 0)
2951         return WINED3DERR_INVALIDCALL;
2952
2953     memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
2954     return WINED3D_OK;
2955 }
2956
2957 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
2958     IWineD3DDevice *iface,
2959     UINT start,
2960     CONST int *srcData,
2961     UINT count) {
2962
2963     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2964     int i, cnt = min(count, MAX_CONST_I - start);
2965
2966     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2967             iface, srcData, start, count);
2968
2969     if (srcData == NULL || cnt < 0)
2970         return WINED3DERR_INVALIDCALL;
2971
2972     memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
2973     for (i = 0; i < cnt; i++)
2974         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
2975            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
2976
2977     for (i = start; i < cnt + start; ++i) {
2978         This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
2979         This->updateStateBlock->set.vertexShaderConstantsI[i]     = TRUE;
2980     }
2981
2982     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
2983
2984     return WINED3D_OK;
2985 }
2986
2987 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
2988     IWineD3DDevice *iface,
2989     UINT start,
2990     int *dstData,
2991     UINT count) {
2992
2993     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2994     int cnt = min(count, MAX_CONST_I - start);
2995
2996     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2997             iface, dstData, start, count);
2998
2999     if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
3000         return WINED3DERR_INVALIDCALL;
3001
3002     memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3003     return WINED3D_OK;
3004 }
3005
3006 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
3007     IWineD3DDevice *iface,
3008     UINT start,
3009     CONST float *srcData,
3010     UINT count) {
3011
3012     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3013     int i;
3014
3015     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3016             iface, srcData, start, count);
3017
3018     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3019     if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
3020         return WINED3DERR_INVALIDCALL;
3021
3022     memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3023     if(TRACE_ON(d3d)) {
3024         for (i = 0; i < count; i++)
3025             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3026                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3027     }
3028
3029     for (i = start; i < count + start; ++i) {
3030         if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
3031             constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_vconstantsF), constants_entry, entry);
3032             if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
3033                 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
3034                 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
3035             }
3036             ptr->idx[ptr->count++] = i;
3037             This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
3038         }
3039         This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
3040     }
3041
3042     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3043
3044     return WINED3D_OK;
3045 }
3046
3047 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3048     IWineD3DDevice *iface,
3049     UINT start,
3050     float *dstData,
3051     UINT count) {
3052
3053     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3054     int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3055
3056     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3057             iface, dstData, start, count);
3058
3059     if (dstData == NULL || cnt < 0)
3060         return WINED3DERR_INVALIDCALL;
3061
3062     memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3063     return WINED3D_OK;
3064 }
3065
3066 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3067     DWORD i;
3068     for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
3069         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3070     }
3071 }
3072
3073 static void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3074     DWORD i, tex;
3075     /* This code can assume that GL_NV_register_combiners are supported, otherwise
3076      * it is never called.
3077      *
3078      * Rules are:
3079      * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3080      * that would be really messy and require shader recompilation
3081      * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3082      * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3083      * -> Whith a 1:1 mapping oneToOneTexUnitMap is set to avoid checking MAX_SAMPLERS array
3084      * entries to make pixel shaders cheaper. MAX_SAMPLERS will be 128 in dx10
3085      */
3086     if(This->stateBlock->pixelShader || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) {
3087         if(This->oneToOneTexUnitMap) {
3088             TRACE("Not touching 1:1 map\n");
3089             return;
3090         }
3091         TRACE("Restoring 1:1 texture unit mapping\n");
3092         /* Restore a 1:1 mapping */
3093         for(i = 0; i < MAX_SAMPLERS; i++) {
3094             if(This->texUnitMap[i] != i) {
3095                 This->texUnitMap[i] = i;
3096                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3097                 markTextureStagesDirty(This, i);
3098             }
3099         }
3100         This->oneToOneTexUnitMap = TRUE;
3101         return;
3102     } else {
3103         /* No pixel shader, and we do not have enough texture units available. Try to skip NULL textures
3104          * First, see if we can succeed at all
3105          */
3106         tex = 0;
3107         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3108             if(This->stateBlock->textures[i] == NULL) tex++;
3109         }
3110
3111         if(GL_LIMITS(textures) + tex < This->stateBlock->lowest_disabled_stage) {
3112             FIXME("Too many bound textures to support the combiner settings\n");
3113             return;
3114         }
3115
3116         /* Now work out the mapping */
3117         tex = 0;
3118         This->oneToOneTexUnitMap = FALSE;
3119         WARN("Non 1:1 mapping UNTESTED!\n");
3120         for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3121             /* Skip NULL textures */
3122             if (!This->stateBlock->textures[i]) {
3123                 /* Map to -1, so the check below doesn't fail if a non-NULL
3124                  * texture is set on this stage */
3125                 TRACE("Mapping texture stage %d to -1\n", i);
3126                 This->texUnitMap[i] = -1;
3127
3128                 continue;
3129             }
3130
3131             TRACE("Mapping texture stage %d to unit %d\n", i, tex);
3132             if(This->texUnitMap[i] != tex) {
3133                 This->texUnitMap[i] = tex;
3134                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3135                 markTextureStagesDirty(This, i);
3136             }
3137
3138             ++tex;
3139         }
3140     }
3141 }
3142
3143 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3144     IWineD3DDeviceImpl *This        = (IWineD3DDeviceImpl *)iface;
3145     IWineD3DPixelShader *oldShader  = This->updateStateBlock->pixelShader;
3146     This->updateStateBlock->pixelShader         = pShader;
3147     This->updateStateBlock->changed.pixelShader = TRUE;
3148     This->updateStateBlock->set.pixelShader     = TRUE;
3149
3150     /* Handle recording of state blocks */
3151     if (This->isRecordingState) {
3152         TRACE("Recording... not performing anything\n");
3153     }
3154
3155     if (This->isRecordingState) {
3156         TRACE("Recording... not performing anything\n");
3157         return WINED3D_OK;
3158     }
3159
3160     if(pShader == oldShader) {
3161         TRACE("App is setting the old pixel shader over, nothing to do\n");
3162         return WINED3D_OK;
3163     }
3164
3165     TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3166     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3167
3168     /* Rebuild the texture unit mapping if nvrc's are supported */
3169     if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3170         IWineD3DDeviceImpl_FindTexUnitMap(This);
3171     }
3172
3173     return WINED3D_OK;
3174 }
3175
3176 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3177     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3178
3179     if (NULL == ppShader) {
3180         WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3181         return WINED3DERR_INVALIDCALL;
3182     }
3183
3184     *ppShader =  This->stateBlock->pixelShader;
3185     if (NULL != *ppShader) {
3186         IWineD3DPixelShader_AddRef(*ppShader);
3187     }
3188     TRACE("(%p) : returning %p\n", This, *ppShader);
3189     return WINED3D_OK;
3190 }
3191
3192 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3193     IWineD3DDevice *iface,
3194     UINT start,
3195     CONST BOOL *srcData,
3196     UINT count) {
3197
3198     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3199     int i, cnt = min(count, MAX_CONST_B - start);
3200
3201     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3202             iface, srcData, start, count);
3203
3204     if (srcData == NULL || cnt < 0)
3205         return WINED3DERR_INVALIDCALL;
3206
3207     memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3208     for (i = 0; i < cnt; i++)
3209         TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3210
3211     for (i = start; i < cnt + start; ++i) {
3212         This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3213         This->updateStateBlock->set.pixelShaderConstantsB[i]     = TRUE;
3214     }
3215
3216     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3217
3218     return WINED3D_OK;
3219 }
3220
3221 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3222     IWineD3DDevice *iface,
3223     UINT start,
3224     BOOL *dstData,
3225     UINT count) {
3226
3227     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3228     int cnt = min(count, MAX_CONST_B - start);
3229
3230     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3231             iface, dstData, start, count);
3232
3233     if (dstData == NULL || cnt < 0)
3234         return WINED3DERR_INVALIDCALL;
3235
3236     memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3237     return WINED3D_OK;
3238 }
3239
3240 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3241     IWineD3DDevice *iface,
3242     UINT start,
3243     CONST int *srcData,
3244     UINT count) {
3245
3246     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3247     int i, cnt = min(count, MAX_CONST_I - start);
3248
3249     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3250             iface, srcData, start, count);
3251
3252     if (srcData == NULL || cnt < 0)
3253         return WINED3DERR_INVALIDCALL;
3254
3255     memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3256     for (i = 0; i < cnt; i++)
3257         TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3258            srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3259
3260     for (i = start; i < cnt + start; ++i) {
3261         This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3262         This->updateStateBlock->set.pixelShaderConstantsI[i]     = TRUE;
3263     }
3264
3265     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3266
3267     return WINED3D_OK;
3268 }
3269
3270 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3271     IWineD3DDevice *iface,
3272     UINT start,
3273     int *dstData,
3274     UINT count) {
3275
3276     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3277     int cnt = min(count, MAX_CONST_I - start);
3278
3279     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3280             iface, dstData, start, count);
3281
3282     if (dstData == NULL || cnt < 0)
3283         return WINED3DERR_INVALIDCALL;
3284
3285     memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3286     return WINED3D_OK;
3287 }
3288
3289 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3290     IWineD3DDevice *iface,
3291     UINT start,
3292     CONST float *srcData,
3293     UINT count) {
3294
3295     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3296     int i;
3297
3298     TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3299             iface, srcData, start, count);
3300
3301     /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3302     if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
3303         return WINED3DERR_INVALIDCALL;
3304
3305     memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3306     if(TRACE_ON(d3d)) {
3307         for (i = 0; i < count; i++)
3308             TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3309                 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3310     }
3311
3312     for (i = start; i < count + start; ++i) {
3313         if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3314             constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_pconstantsF), constants_entry, entry);
3315             if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
3316                 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
3317                 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3318             }
3319             ptr->idx[ptr->count++] = i;
3320             This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3321         }
3322         This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3323     }
3324
3325     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3326
3327     return WINED3D_OK;
3328 }
3329
3330 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3331     IWineD3DDevice *iface,
3332     UINT start,
3333     float *dstData,
3334     UINT count) {
3335
3336     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3337     int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3338
3339     TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3340             iface, dstData, start, count);
3341
3342     if (dstData == NULL || cnt < 0)
3343         return WINED3DERR_INVALIDCALL;
3344
3345     memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3346     return WINED3D_OK;
3347 }
3348
3349 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3350 static HRESULT
3351 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3352     char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
3353     unsigned int i;
3354     DWORD DestFVF = dest->fvf;
3355     WINED3DVIEWPORT vp;
3356     WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3357     BOOL doClip;
3358     int numTextures;
3359
3360     if (SrcFVF & WINED3DFVF_NORMAL) {
3361         WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3362     }
3363
3364     if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
3365         ERR("Source has no position mask\n");
3366         return WINED3DERR_INVALIDCALL;
3367     }
3368
3369     /* We might access VBOs from this code, so hold the lock */
3370     ENTER_GL();
3371
3372     if (dest->resource.allocatedMemory == NULL) {
3373         /* This may happen if we do direct locking into a vbo. Unlikely,
3374          * but theoretically possible(ddraw processvertices test)
3375          */
3376         dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3377         if(!dest->resource.allocatedMemory) {
3378             LEAVE_GL();
3379             ERR("Out of memory\n");
3380             return E_OUTOFMEMORY;
3381         }
3382         if(dest->vbo) {
3383             void *src;
3384             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3385             checkGLcall("glBindBufferARB");
3386             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3387             if(src) {
3388                 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3389             }
3390             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3391             checkGLcall("glUnmapBufferARB");
3392         }
3393     }
3394
3395     /* Get a pointer into the destination vbo(create one if none exists) and
3396      * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3397      */
3398     if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3399         CreateVBO(dest);
3400     }
3401
3402     if(dest->vbo) {
3403         dest_conv_addr = HeapAlloc(GetProcessHeap(), 0, dwCount * get_flexible_vertex_size(DestFVF));
3404         if(!dest_conv_addr) {
3405             ERR("Out of memory\n");
3406             /* Continue without storing converted vertices */
3407         }
3408         dest_conv = dest_conv_addr;
3409     }
3410
3411     /* Should I clip?
3412      * a) WINED3DRS_CLIPPING is enabled
3413      * b) WINED3DVOP_CLIP is passed
3414      */
3415     if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3416         static BOOL warned = FALSE;
3417         /*
3418          * The clipping code is not quite correct. Some things need
3419          * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3420          * so disable clipping for now.
3421          * (The graphics in Half-Life are broken, and my processvertices
3422          *  test crashes with IDirect3DDevice3)
3423         doClip = TRUE;
3424          */
3425         doClip = FALSE;
3426         if(!warned) {
3427            warned = TRUE;
3428            FIXME("Clipping is broken and disabled for now\n");
3429         }
3430     } else doClip = FALSE;
3431     dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3432
3433     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3434                                  WINED3DTS_VIEW,
3435                                  &view_mat);
3436     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3437                                  WINED3DTS_PROJECTION,
3438                                  &proj_mat);
3439     IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3440                                  WINED3DTS_WORLDMATRIX(0),
3441                                  &world_mat);
3442
3443     TRACE("View mat:\n");
3444     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);
3445     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);
3446     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);
3447     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);
3448
3449     TRACE("Proj mat:\n");
3450     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);
3451     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);
3452     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);
3453     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);
3454
3455     TRACE("World mat:\n");
3456     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);
3457     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);
3458     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);
3459     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);
3460
3461     /* Get the viewport */
3462     IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3463     TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3464           vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3465
3466     multiply_matrix(&mat,&view_mat,&world_mat);
3467     multiply_matrix(&mat,&proj_mat,&mat);
3468
3469     numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3470
3471     for (i = 0; i < dwCount; i+= 1) {
3472         unsigned int tex_index;
3473
3474         if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3475              ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3476             /* The position first */
3477             float *p =
3478               (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
3479             float x, y, z, rhw;
3480             TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3481
3482             /* Multiplication with world, view and projection matrix */
3483             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);
3484             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);
3485             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);
3486             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);
3487
3488             TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3489
3490             /* WARNING: The following things are taken from d3d7 and were not yet checked
3491              * against d3d8 or d3d9!
3492              */
3493
3494             /* Clipping conditions: From
3495              * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
3496              *
3497              * A vertex is clipped if it does not match the following requirements
3498              * -rhw < x <= rhw
3499              * -rhw < y <= rhw
3500              *    0 < z <= rhw
3501              *    0 < rhw ( Not in d3d7, but tested in d3d7)
3502              *
3503              * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3504              * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3505              *
3506              */
3507
3508             if( !doClip ||
3509                 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3510                   (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) && 
3511                   ( rhw > eps ) ) ) {
3512
3513                 /* "Normal" viewport transformation (not clipped)
3514                  * 1) The values are divided by rhw
3515                  * 2) The y axis is negative, so multiply it with -1
3516                  * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3517                  *    -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3518                  * 4) Multiply x with Width/2 and add Width/2
3519                  * 5) The same for the height
3520                  * 6) Add the viewpoint X and Y to the 2D coordinates and
3521                  *    The minimum Z value to z
3522                  * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3523                  *
3524                  * Well, basically it's simply a linear transformation into viewport
3525                  * coordinates
3526                  */
3527
3528                 x /= rhw;
3529                 y /= rhw;
3530                 z /= rhw;
3531
3532                 y *= -1;
3533
3534                 x *= vp.Width / 2;
3535                 y *= vp.Height / 2;
3536                 z *= vp.MaxZ - vp.MinZ;
3537
3538                 x += vp.Width / 2 + vp.X;
3539                 y += vp.Height / 2 + vp.Y;
3540                 z += vp.MinZ;
3541
3542                 rhw = 1 / rhw;
3543             } else {
3544                 /* That vertex got clipped
3545                  * Contrary to OpenGL it is not dropped completely, it just
3546                  * undergoes a different calculation.
3547                  */
3548                 TRACE("Vertex got clipped\n");
3549                 x += rhw;
3550                 y += rhw;
3551
3552                 x  /= 2;
3553                 y  /= 2;
3554
3555                 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3556                  * outside of the main vertex buffer memory. That needs some more
3557                  * investigation...
3558                  */
3559             }
3560
3561             TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3562
3563
3564             ( (float *) dest_ptr)[0] = x;
3565             ( (float *) dest_ptr)[1] = y;
3566             ( (float *) dest_ptr)[2] = z;
3567             ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3568
3569             dest_ptr += 3 * sizeof(float);
3570
3571             if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3572                 dest_ptr += sizeof(float);
3573             }
3574
3575             if(dest_conv) {
3576                 float w = 1 / rhw;
3577                 ( (float *) dest_conv)[0] = x * w;
3578                 ( (float *) dest_conv)[1] = y * w;
3579                 ( (float *) dest_conv)[2] = z * w;
3580                 ( (float *) dest_conv)[3] = w;
3581
3582                 dest_conv += 3 * sizeof(float);
3583
3584                 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3585                     dest_conv += sizeof(float);
3586                 }
3587             }
3588         }
3589         if (DestFVF & WINED3DFVF_PSIZE) {
3590             dest_ptr += sizeof(DWORD);
3591             if(dest_conv) dest_conv += sizeof(DWORD);
3592         }
3593         if (DestFVF & WINED3DFVF_NORMAL) {
3594             float *normal =
3595               (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
3596             /* AFAIK this should go into the lighting information */
3597             FIXME("Didn't expect the destination to have a normal\n");
3598             copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3599             if(dest_conv) {
3600                 copy_and_next(dest_conv, normal, 3 * sizeof(float));
3601             }
3602         }
3603
3604         if (DestFVF & WINED3DFVF_DIFFUSE) {
3605             DWORD *color_d = 
3606               (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
3607             if(!color_d) {
3608                 static BOOL warned = FALSE;
3609
3610                 if(!warned) {
3611                     ERR("No diffuse color in source, but destination has one\n");
3612                     warned = TRUE;
3613                 }
3614
3615                 *( (DWORD *) dest_ptr) = 0xffffffff;
3616                 dest_ptr += sizeof(DWORD);
3617
3618                 if(dest_conv) {
3619                     *( (DWORD *) dest_conv) = 0xffffffff;
3620                     dest_conv += sizeof(DWORD);
3621                 }
3622             }
3623             else {
3624                 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3625                 if(dest_conv) {
3626                     *( (DWORD *) dest_conv)  = (*color_d & 0xff00ff00)      ; /* Alpha + green */
3627                     *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
3628                     *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
3629                     dest_conv += sizeof(DWORD);
3630                 }
3631             }
3632         }
3633
3634         if (DestFVF & WINED3DFVF_SPECULAR) { 
3635             /* What's the color value in the feedback buffer? */
3636             DWORD *color_s = 
3637               (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
3638             if(!color_s) {
3639                 static BOOL warned = FALSE;
3640
3641                 if(!warned) {
3642                     ERR("No specular color in source, but destination has one\n");
3643                     warned = TRUE;
3644                 }
3645
3646                 *( (DWORD *) dest_ptr) = 0xFF000000;
3647                 dest_ptr += sizeof(DWORD);
3648
3649                 if(dest_conv) {
3650                     *( (DWORD *) dest_conv) = 0xFF000000;
3651                     dest_conv += sizeof(DWORD);
3652                 }
3653             }
3654             else {
3655                 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3656                 if(dest_conv) {
3657                     *( (DWORD *) dest_conv)  = (*color_s & 0xff00ff00)      ; /* Alpha + green */
3658                     *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
3659                     *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
3660                     dest_conv += sizeof(DWORD);
3661                 }
3662             }
3663         }
3664
3665         for (tex_index = 0; tex_index < numTextures; tex_index++) {
3666             float *tex_coord =
3667               (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) + 
3668                             i * lpStrideData->u.s.texCoords[tex_index].dwStride);
3669             if(!tex_coord) {
3670                 ERR("No source texture, but destination requests one\n");
3671                 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3672                 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3673             }
3674             else {
3675                 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3676                 if(dest_conv) {
3677                     copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3678                 }
3679             }
3680         }
3681     }
3682
3683     if(dest_conv) {
3684         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3685         checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
3686         GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
3687                                       dwCount * get_flexible_vertex_size(DestFVF),
3688                                       dest_conv_addr));
3689         checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
3690         HeapFree(GetProcessHeap(), 0, dest_conv_addr);
3691     }
3692
3693     LEAVE_GL();
3694
3695     return WINED3D_OK;
3696 }
3697 #undef copy_and_next
3698
3699 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3700     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3701     IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
3702     WineDirect3DVertexStridedData strided;
3703     TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
3704
3705     if (!SrcImpl) {
3706         WARN("NULL source vertex buffer\n");
3707         return WINED3DERR_INVALIDCALL;
3708     }
3709
3710     /* Need any context to write to the vbo. In a non-multithreaded environment a context is there anyway,
3711      * and this call is quite performance critical, so don't call needlessly
3712      */
3713     if(This->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) {
3714         ENTER_GL();
3715         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
3716         LEAVE_GL();
3717     }
3718
3719     /* We don't need the source vbo because this buffer is only used as
3720      * a source for ProcessVertices. Avoid wasting resources by converting the
3721      * buffer and loading the VBO
3722      */
3723     if(SrcImpl->vbo) {
3724         TRACE("Releasing the source vbo, it won't be needed\n");
3725
3726         if(!SrcImpl->resource.allocatedMemory) {
3727             /* Rescue the data from the buffer */
3728             void *src;
3729             SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
3730             if(!SrcImpl->resource.allocatedMemory) {
3731                 ERR("Out of memory\n");
3732                 return E_OUTOFMEMORY;
3733             }
3734
3735             ENTER_GL();
3736             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
3737             checkGLcall("glBindBufferARB");
3738
3739             src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3740             if(src) {
3741                 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
3742             }
3743
3744             GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3745             checkGLcall("glUnmapBufferARB");
3746         } else {
3747             ENTER_GL();
3748         }
3749
3750         GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
3751         checkGLcall("glBindBufferARB");
3752         GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
3753         checkGLcall("glDeleteBuffersARB");
3754         LEAVE_GL();
3755
3756         SrcImpl->vbo = 0;
3757     }
3758
3759     memset(&strided, 0, sizeof(strided));
3760     primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0, 0);
3761
3762     return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
3763 }
3764
3765 /*****
3766  * Get / Set Texture Stage States
3767  * TODO: Verify against dx9 definitions
3768  *****/
3769 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3770     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3771     DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
3772
3773     /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3774
3775     TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3776
3777     This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3778     This->updateStateBlock->set.textureState[Stage][Type]     = TRUE;
3779     This->updateStateBlock->textureState[Stage][Type]         = Value;
3780
3781     if (This->isRecordingState) {
3782         TRACE("Recording... not performing anything\n");
3783         return WINED3D_OK;
3784     }
3785
3786     /* Checked after the assignments to allow proper stateblock recording */
3787     if(oldValue == Value) {
3788         TRACE("App is setting the old value over, nothing to do\n");
3789         return WINED3D_OK;
3790     }
3791
3792     if(Stage > This->stateBlock->lowest_disabled_stage &&
3793        StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
3794         /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
3795          * Changes in other states are important on disabled stages too
3796          */
3797         return WINED3D_OK;
3798     }
3799
3800     if(Type == WINED3DTSS_COLOROP) {
3801         int i;
3802
3803         if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
3804             /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
3805              * they have to be disabled
3806              *
3807              * The current stage is dirtified below.
3808              */
3809             for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
3810                 TRACE("Additionally dirtifying stage %d\n", i);
3811                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3812             }
3813             This->stateBlock->lowest_disabled_stage = Stage;
3814             TRACE("New lowest disabled: %d\n", Stage);
3815         } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
3816             /* Previously disabled stage enabled. Stages above it may need enabling
3817              * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
3818              * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
3819              *
3820              * Again stage Stage doesn't need to be dirtified here, it is handled below.
3821              */
3822
3823             for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
3824                 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
3825                     break;
3826                 }
3827                 TRACE("Additionally dirtifying stage %d due to enable\n", i);
3828                 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3829             }
3830             This->stateBlock->lowest_disabled_stage = i;
3831             TRACE("New lowest disabled: %d\n", i);
3832         }
3833         if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3834             /* TODO: Built a stage -> texture unit mapping for register combiners */
3835         }
3836     }
3837
3838     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
3839
3840     /* Rebuild the stage -> gl texture unit mapping if register combiners are supported
3841      * If there is a pixel shader there will be a 1:1 mapping, no need to touch it. SetPixelShader
3842      * will call FindTexUnitMap too.
3843      */
3844     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3845         IWineD3DDeviceImpl_FindTexUnitMap(This);
3846     }
3847     return WINED3D_OK;
3848 }
3849
3850 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3851     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3852     TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3853     *pValue = This->updateStateBlock->textureState[Stage][Type];
3854     return WINED3D_OK;
3855 }
3856
3857 /*****
3858  * Get / Set Texture
3859  *****/
3860 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3861
3862     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3863     IWineD3DBaseTexture   *oldTexture;
3864
3865     oldTexture = This->updateStateBlock->textures[Stage];
3866     TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
3867
3868 #if 0 /* TODO: check so vertex textures */
3869     if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
3870         This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
3871         return WINED3D_OK;
3872     }
3873 #endif
3874
3875     if(pTexture != NULL) {
3876         /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH; 
3877          */
3878         if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
3879             WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
3880             return WINED3DERR_INVALIDCALL;
3881         }
3882         This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
3883     }
3884
3885     TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
3886     TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
3887
3888     This->updateStateBlock->set.textures[Stage]     = TRUE;
3889     This->updateStateBlock->changed.textures[Stage] = TRUE;
3890     TRACE("(%p) : setting new texture to %p\n", This, pTexture);
3891     This->updateStateBlock->textures[Stage]         = pTexture;
3892
3893     /* Handle recording of state blocks */
3894     if (This->isRecordingState) {
3895         TRACE("Recording... not performing anything\n");
3896         return WINED3D_OK;
3897     }
3898
3899     if(oldTexture == pTexture) {
3900         TRACE("App is setting the same texture again, nothing to do\n");
3901         return WINED3D_OK;
3902     }
3903
3904     /** NOTE: MSDN says that setTexture increases the reference count,
3905     * and the the application nust set the texture back to null (or have a leaky application),
3906     * This means we should pass the refcount up to the parent
3907      *******************************/
3908     if (NULL != This->updateStateBlock->textures[Stage]) {
3909         IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
3910         ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
3911
3912         IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
3913         if(oldTexture == NULL && Stage < MAX_TEXTURES) {
3914             /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
3915              * so the COLOROP and ALPHAOP have to be dirtified.
3916              */
3917             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
3918             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
3919         }
3920         if(bindCount == 1) {
3921             new->baseTexture.sampler = Stage;
3922         }
3923         /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
3924
3925     }
3926
3927     if (NULL != oldTexture) {
3928         IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
3929         LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
3930
3931         IWineD3DBaseTexture_Release(oldTexture);
3932         if(pTexture == NULL && Stage < MAX_TEXTURES) {
3933             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
3934             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
3935         }
3936
3937         if(bindCount && old->baseTexture.sampler == Stage) {
3938             int i;
3939             /* Have to do a search for the other sampler(s) where the texture is bound to
3940              * Shouldn't happen as long as apps bind a texture only to one stage
3941              */
3942             TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
3943             for(i = 0; i < GL_LIMITS(sampler_stages); i++) {
3944                 if(This->updateStateBlock->textures[i] == oldTexture) {
3945                     old->baseTexture.sampler = i;
3946                     break;
3947                 }
3948             }
3949         }
3950     }
3951
3952     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
3953
3954     /* Verify the texture unit mapping(and rebuild it if needed) if we use nvrcs and no
3955      * pixel shader is used
3956      */
3957     if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3958         IWineD3DDeviceImpl_FindTexUnitMap(This);
3959     }
3960
3961     return WINED3D_OK;
3962 }
3963
3964 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3965     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3966     TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
3967
3968     *ppTexture=This->stateBlock->textures[Stage];
3969     if (*ppTexture)
3970         IWineD3DBaseTexture_AddRef(*ppTexture);
3971
3972     return WINED3D_OK;
3973 }
3974
3975 /*****
3976  * Get Back Buffer
3977  *****/
3978 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
3979                                                 IWineD3DSurface **ppBackBuffer) {
3980     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3981     IWineD3DSwapChain *swapChain;
3982     HRESULT hr;
3983
3984     TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3985
3986     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, &swapChain);
3987     if (hr == WINED3D_OK) {
3988         hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
3989             IWineD3DSwapChain_Release(swapChain);
3990     } else {
3991         *ppBackBuffer = NULL;
3992     }
3993     return hr;
3994 }
3995
3996 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
3997     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3998     WARN("(%p) : stub, calling idirect3d for now\n", This);
3999     return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4000 }
4001
4002 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
4003     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4004     IWineD3DSwapChain *swapChain;
4005     HRESULT hr;
4006
4007     if(iSwapChain > 0) {
4008         hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4009         if (hr == WINED3D_OK) {
4010             hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4011             IWineD3DSwapChain_Release(swapChain);
4012         } else {
4013             FIXME("(%p) Error getting display mode\n", This);
4014         }
4015     } else {
4016         /* Don't read the real display mode,
4017            but return the stored mode instead. X11 can't change the color
4018            depth, and some apps are pretty angry if they SetDisplayMode from
4019            24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
4020
4021            Also don't relay to the swapchain because with ddraw it's possible
4022            that there isn't a swapchain at all */
4023         pMode->Width = This->ddraw_width;
4024         pMode->Height = This->ddraw_height;
4025         pMode->Format = This->ddraw_format;
4026         pMode->RefreshRate = 0;
4027         hr = WINED3D_OK;
4028     }
4029
4030     return hr;
4031 }
4032
4033 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
4034     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4035     TRACE("(%p)->(%p)\n", This, hWnd);
4036
4037     if(This->ddraw_fullscreen) {
4038         if(This->ddraw_window && This->ddraw_window != hWnd) {
4039             IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
4040         }
4041         if(hWnd && This->ddraw_window != hWnd) {
4042             IWineD3DDeviceImpl_SetupFullscreenWindow(iface, hWnd);
4043         }
4044     }
4045
4046     This->ddraw_window = hWnd;
4047     return WINED3D_OK;
4048 }
4049
4050 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
4051     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4052     TRACE("(%p)->(%p)\n", This, hWnd);
4053
4054     *hWnd = This->ddraw_window;
4055     return WINED3D_OK;
4056 }
4057
4058 /*****
4059  * Stateblock related functions
4060  *****/
4061
4062 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4063     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4064     IWineD3DStateBlockImpl *object;
4065     HRESULT temp_result;
4066     int i;
4067
4068     TRACE("(%p)\n", This);
4069     
4070     if (This->isRecordingState) {
4071         return WINED3DERR_INVALIDCALL;
4072     }
4073     
4074     object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4075     if (NULL == object ) {
4076         FIXME("(%p)Error allocating memory for stateblock\n", This);
4077         return E_OUTOFMEMORY;
4078     }
4079     TRACE("(%p) created object %p\n", This, object);
4080     object->wineD3DDevice= This;
4081     /** FIXME: object->parent       = parent; **/
4082     object->parent       = NULL;
4083     object->blockType    = WINED3DSBT_ALL;
4084     object->ref          = 1;
4085     object->lpVtbl       = &IWineD3DStateBlock_Vtbl;
4086
4087     for(i = 0; i < LIGHTMAP_SIZE; i++) {
4088         list_init(&object->lightMap[i]);
4089     }
4090
4091     temp_result = allocate_shader_constants(object);
4092     if (WINED3D_OK != temp_result)
4093         return temp_result;
4094
4095     IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4096     This->updateStateBlock = object;
4097     This->isRecordingState = TRUE;
4098
4099     TRACE("(%p) recording stateblock %p\n",This , object);
4100     return WINED3D_OK;
4101 }
4102
4103 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4104     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4105
4106     if (!This->isRecordingState) {
4107         FIXME("(%p) not recording! returning error\n", This);
4108         *ppStateBlock = NULL;
4109         return WINED3DERR_INVALIDCALL;
4110     }
4111
4112     *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4113     This->isRecordingState = FALSE;
4114     This->updateStateBlock = This->stateBlock;
4115     IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4116     /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4117     TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4118     return WINED3D_OK;
4119 }
4120
4121 /*****
4122  * Scene related functions
4123  *****/
4124 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4125     /* At the moment we have no need for any functionality at the beginning
4126        of a scene                                                          */
4127     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4128     TRACE("(%p)\n", This);
4129
4130     if(This->inScene) {
4131         TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4132         return WINED3DERR_INVALIDCALL;
4133     }
4134     This->inScene = TRUE;
4135     return WINED3D_OK;
4136 }
4137
4138 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4139     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4140     TRACE("(%p)\n", This);
4141
4142     if(!This->inScene) {
4143         TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4144         return WINED3DERR_INVALIDCALL;
4145     }
4146
4147     ENTER_GL();
4148     if(This->createParms.BehaviorFlags & WINED3DCREATE_MULTITHREADED) {
4149         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4150     }
4151     /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4152     glFlush();
4153     checkGLcall("glFlush");
4154     LEAVE_GL();
4155
4156     This->inScene = FALSE;
4157     return WINED3D_OK;
4158 }
4159
4160 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4161                                           CONST RECT* pSourceRect, CONST RECT* pDestRect,
4162                                           HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4163     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4164     IWineD3DSwapChain *swapChain = NULL;
4165     int i;
4166     int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4167
4168     TRACE("(%p) Presenting the frame\n", This);
4169
4170     for(i = 0 ; i < swapchains ; i ++) {
4171
4172         IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4173         TRACE("presentinng chain %d, %p\n", i, swapChain);
4174         IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4175         IWineD3DSwapChain_Release(swapChain);
4176     }
4177
4178     return WINED3D_OK;
4179 }
4180
4181 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4182                                         DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4183     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4184     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)This->render_targets[0];
4185
4186     GLbitfield     glMask = 0;
4187     unsigned int   i;
4188     CONST WINED3DRECT* curRect;
4189
4190     TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
4191           Count, pRects, Flags, Z, Stencil);
4192
4193     if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) {
4194         WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4195         /* TODO: What about depth stencil buffers without stencil bits? */
4196         return WINED3DERR_INVALIDCALL;
4197     }
4198
4199     ENTER_GL();
4200     /* This is for offscreen rendering as well as for multithreading, thus activate the set render target
4201      * and not the last active one.
4202      */
4203
4204     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4205         apply_fbo_state(iface);
4206     }
4207
4208     ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
4209
4210     glEnable(GL_SCISSOR_TEST);
4211     checkGLcall("glEnable GL_SCISSOR_TEST");
4212     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
4213     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
4214
4215     if (Count > 0 && pRects) {
4216         curRect = pRects;
4217     } else {
4218         curRect = NULL;
4219     }
4220
4221     /* Only set the values up once, as they are not changing */
4222     if (Flags & WINED3DCLEAR_STENCIL) {
4223         glClearStencil(Stencil);
4224         checkGLcall("glClearStencil");
4225         glMask = glMask | GL_STENCIL_BUFFER_BIT;
4226         glStencilMask(0xFFFFFFFF);
4227     }
4228
4229     if (Flags & WINED3DCLEAR_ZBUFFER) {
4230         glDepthMask(GL_TRUE);
4231         glClearDepth(Z);
4232         checkGLcall("glClearDepth");
4233         glMask = glMask | GL_DEPTH_BUFFER_BIT;
4234         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4235     }
4236
4237     if (Flags & WINED3DCLEAR_TARGET) {
4238         TRACE("Clearing screen with glClear to color %x\n", Color);
4239         glClearColor(D3DCOLOR_R(Color),
4240                      D3DCOLOR_G(Color),
4241                      D3DCOLOR_B(Color),
4242                      D3DCOLOR_A(Color));
4243         checkGLcall("glClearColor");
4244
4245         /* Clear ALL colors! */
4246         glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4247         glMask = glMask | GL_COLOR_BUFFER_BIT;
4248     }
4249
4250     if (!curRect) {
4251         /* In drawable flag is set below */
4252
4253         glScissor(This->stateBlock->viewport.X,
4254                   (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
4255                   (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4256                    This->stateBlock->viewport.Width,
4257                    This->stateBlock->viewport.Height);
4258         checkGLcall("glScissor");
4259         glClear(glMask);
4260         checkGLcall("glClear");
4261     } else {
4262         if(!(target->Flags & SFLAG_INDRAWABLE) &&
4263            !(wined3d_settings.offscreen_rendering_mode == ORM_FBO && This->render_offscreen && target->Flags & SFLAG_INTEXTURE)) {
4264
4265             if(curRect[0].x1 > 0 || curRect[0].y1 > 0 ||
4266                curRect[0].x2 < target->currentDesc.Width ||
4267                curRect[0].y2 < target->currentDesc.Height) {
4268                 TRACE("Partial clear, and surface not in drawable. Blitting texture to drawable\n");
4269                 blt_to_drawable(This, target);
4270             }
4271         }
4272
4273         /* Now process each rect in turn */
4274         for (i = 0; i < Count; i++) {
4275             /* Note gl uses lower left, width/height */
4276             TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4277                   curRect[i].x1, curRect[i].y1, curRect[i].x2, curRect[i].y2,
4278                   curRect[i].x1, (target->currentDesc.Height - curRect[i].y2),
4279                   curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4280
4281             /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
4282              * The rectangle is not cleared, no error is returned, but further rectanlges are
4283              * still cleared if they are valid
4284              */
4285             if(curRect[i].x1 > curRect[i].x2 || curRect[i].y1 > curRect[i].y2) {
4286                 TRACE("Rectangle with negative dimensions, ignoring\n");
4287                 continue;
4288             }
4289
4290             if(This->render_offscreen) {
4291                 glScissor(curRect[i].x1, curRect[i].y1,
4292                           curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4293             } else {
4294                 glScissor(curRect[i].x1, target->currentDesc.Height - curRect[i].y2,
4295                           curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4296             }
4297             checkGLcall("glScissor");
4298
4299             glClear(glMask);
4300             checkGLcall("glClear");
4301         }
4302     }
4303
4304     /* Restore the old values (why..?) */
4305     if (Flags & WINED3DCLEAR_STENCIL) {
4306         glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4307     }
4308     if (Flags & WINED3DCLEAR_TARGET) {
4309         DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
4310         glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4311                     mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4312                     mask & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
4313                     mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4314     }
4315
4316     LEAVE_GL();
4317
4318     /* Dirtify the target surface for now. If the surface is locked regularily, and an up to date sysmem copy exists,
4319      * it is most likely more efficient to perform a clear on the sysmem copy too isntead of downloading it
4320      */
4321     if(This->render_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4322         target->Flags |= SFLAG_INTEXTURE;
4323         target->Flags &= ~SFLAG_INSYSMEM;
4324     } else {
4325         target->Flags |= SFLAG_INDRAWABLE;
4326         target->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INSYSMEM);
4327     }
4328     return WINED3D_OK;
4329 }
4330
4331 /*****
4332  * Drawing functions
4333  *****/
4334 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4335                                                 UINT PrimitiveCount) {
4336
4337     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4338
4339     TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4340                                debug_d3dprimitivetype(PrimitiveType),
4341                                StartVertex, PrimitiveCount);
4342
4343     /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4344     if(This->stateBlock->streamIsUP) {
4345         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4346         This->stateBlock->streamIsUP = FALSE;
4347     }
4348
4349     if(This->stateBlock->loadBaseVertexIndex != 0) {
4350         This->stateBlock->loadBaseVertexIndex = 0;
4351         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4352     }
4353     /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4354     drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4355                   0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4356     return WINED3D_OK;
4357 }
4358
4359 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4360 static HRESULT  WINAPI  IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4361                                                            WINED3DPRIMITIVETYPE PrimitiveType,
4362                                                            UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4363
4364     IWineD3DDeviceImpl  *This = (IWineD3DDeviceImpl *)iface;
4365     UINT                 idxStride = 2;
4366     IWineD3DIndexBuffer *pIB;
4367     WINED3DINDEXBUFFER_DESC  IdxBufDsc;
4368     GLuint vbo;
4369
4370     if(This->stateBlock->streamIsUP) {
4371         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4372         This->stateBlock->streamIsUP = FALSE;
4373     }
4374     pIB = This->stateBlock->pIndexData;
4375     vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
4376
4377     TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
4378           PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4379           minIndex, NumVertices, startIndex, primCount);
4380
4381     IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4382     if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4383         idxStride = 2;
4384     } else {
4385         idxStride = 4;
4386     }
4387
4388     if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4389         This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4390         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4391     }
4392
4393     drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
4394                    idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4395
4396     return WINED3D_OK;
4397 }
4398
4399 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4400                                                     UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4401                                                     UINT VertexStreamZeroStride) {
4402     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4403
4404     TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4405              debug_d3dprimitivetype(PrimitiveType),
4406              PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4407
4408     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4409     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4410     This->stateBlock->streamOffset[0] = 0;
4411     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4412     This->stateBlock->streamIsUP = TRUE;
4413     This->stateBlock->loadBaseVertexIndex = 0;
4414
4415     /* TODO: Only mark dirty if drawing from a different UP address */
4416     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4417
4418     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0  /* NumVertices */,
4419                   0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4420
4421     /* MSDN specifies stream zero settings must be set to NULL */
4422     This->stateBlock->streamStride[0] = 0;
4423     This->stateBlock->streamSource[0] = NULL;
4424
4425     /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4426      * the new stream sources or use UP drawing again
4427      */
4428     return WINED3D_OK;
4429 }
4430
4431 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4432                                                              UINT MinVertexIndex, UINT NumVertices,
4433                                                              UINT PrimitiveCount, CONST void* pIndexData,
4434                                                              WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4435                                                              UINT VertexStreamZeroStride) {
4436     int                 idxStride;
4437     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4438
4439     TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4440              This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4441              MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4442              IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4443
4444     if (IndexDataFormat == WINED3DFMT_INDEX16) {
4445         idxStride = 2;
4446     } else {
4447         idxStride = 4;
4448     }
4449
4450     /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4451     This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4452     This->stateBlock->streamIsUP = TRUE;
4453     This->stateBlock->streamOffset[0] = 0;
4454     This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4455
4456     /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4457     This->stateBlock->baseVertexIndex = 0;
4458     This->stateBlock->loadBaseVertexIndex = 0;
4459     /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4460     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4461     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4462
4463     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4464
4465     /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4466     This->stateBlock->streamSource[0] = NULL;
4467     This->stateBlock->streamStride[0] = 0;
4468     This->stateBlock->pIndexData = NULL;
4469     /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4470      * SetStreamSource to specify a vertex buffer
4471      */
4472
4473     return WINED3D_OK;
4474 }
4475
4476 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4477     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4478
4479     /* Mark the state dirty until we have nicer tracking
4480      * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4481      * that value.
4482      */
4483     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4484     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4485     This->stateBlock->baseVertexIndex = 0;
4486     This->up_strided = DrawPrimStrideData;
4487     This->stateBlock->streamIsUP = TRUE;
4488     drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
4489     This->up_strided = NULL;
4490     return WINED3D_OK;
4491 }
4492  /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4493 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture,  IWineD3DBaseTexture *pDestinationTexture){
4494     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4495     HRESULT hr = WINED3D_OK;
4496     WINED3DRESOURCETYPE sourceType;
4497     WINED3DRESOURCETYPE destinationType;
4498     int i ,levels;
4499
4500     /* TODO: think about moving the code into IWineD3DBaseTexture  */
4501
4502     TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4503
4504     /* verify that the source and destination textures aren't NULL */
4505     if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4506         WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4507              This, pSourceTexture, pDestinationTexture);
4508         hr = WINED3DERR_INVALIDCALL;
4509     }
4510
4511     if (pSourceTexture == pDestinationTexture) {
4512         WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4513              This, pSourceTexture, pDestinationTexture);
4514         hr = WINED3DERR_INVALIDCALL;
4515     }
4516     /* Verify that the source and destination textures are the same type */
4517     sourceType      = IWineD3DBaseTexture_GetType(pSourceTexture);
4518     destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4519
4520     if (sourceType != destinationType) {
4521         WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
4522              This);
4523         hr = WINED3DERR_INVALIDCALL;
4524     }
4525
4526     /* check that both textures have the identical numbers of levels  */
4527     if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture)  != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4528         WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4529         hr = WINED3DERR_INVALIDCALL;
4530     }
4531
4532     if (WINED3D_OK == hr) {
4533
4534         /* Make sure that the destination texture is loaded */
4535         IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4536
4537         /* Update every surface level of the texture */
4538         levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4539
4540         switch (sourceType) {
4541         case WINED3DRTYPE_TEXTURE:
4542             {
4543                 IWineD3DSurface *srcSurface;
4544                 IWineD3DSurface *destSurface;
4545
4546                 for (i = 0 ; i < levels ; ++i) {
4547                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture,      i, &srcSurface);
4548                     IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4549                     hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4550                     IWineD3DSurface_Release(srcSurface);
4551                     IWineD3DSurface_Release(destSurface);
4552                     if (WINED3D_OK != hr) {
4553                         WARN("(%p) : Call to update surface failed\n", This);
4554                         return hr;
4555                     }
4556                 }
4557             }
4558             break;
4559         case WINED3DRTYPE_CUBETEXTURE:
4560             {
4561                 IWineD3DSurface *srcSurface;
4562                 IWineD3DSurface *destSurface;
4563                 WINED3DCUBEMAP_FACES faceType;
4564
4565                 for (i = 0 ; i < levels ; ++i) {
4566                     /* Update each cube face */
4567                     for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4568                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture,      faceType, i, &srcSurface);
4569                         if (WINED3D_OK != hr) {
4570                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4571                         } else {
4572                             TRACE("Got srcSurface %p\n", srcSurface);
4573                         }
4574                         hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4575                         if (WINED3D_OK != hr) {
4576                             FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4577                         } else {
4578                             TRACE("Got desrSurface %p\n", destSurface);
4579                         }
4580                         hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4581                         IWineD3DSurface_Release(srcSurface);
4582                         IWineD3DSurface_Release(destSurface);
4583                         if (WINED3D_OK != hr) {
4584                             WARN("(%p) : Call to update surface failed\n", This);
4585                             return hr;
4586                         }
4587                     }
4588                 }
4589             }
4590             break;
4591 #if 0 /* TODO: Add support for volume textures */
4592         case WINED3DRTYPE_VOLUMETEXTURE:
4593             {
4594                 IWineD3DVolume  srcVolume  = NULL;
4595                 IWineD3DSurface destVolume = NULL;
4596
4597                 for (i = 0 ; i < levels ; ++i) {
4598                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture,      i, &srcVolume);
4599                     IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4600                     hr =  IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4601                     IWineD3DVolume_Release(srcSurface);
4602                     IWineD3DVolume_Release(destSurface);
4603                     if (WINED3D_OK != hr) {
4604                         WARN("(%p) : Call to update volume failed\n", This);
4605                         return hr;
4606                     }
4607                 }
4608             }
4609             break;
4610 #endif
4611         default:
4612             FIXME("(%p) : Unsupported source and destination type\n", This);
4613             hr = WINED3DERR_INVALIDCALL;
4614         }
4615     }
4616
4617     return hr;
4618 }
4619
4620 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4621     IWineD3DSwapChain *swapChain;
4622     HRESULT hr;
4623     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4624     if(hr == WINED3D_OK) {
4625         hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4626                 IWineD3DSwapChain_Release(swapChain);
4627     }
4628     return hr;
4629 }
4630
4631 static HRESULT  WINAPI  IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4632     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4633     /* return a sensible default */
4634     *pNumPasses = 1;
4635     /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
4636     FIXME("(%p) : stub\n", This);
4637     return WINED3D_OK;
4638 }
4639
4640 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4641     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4642     int j;
4643     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4644     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4645         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4646         return WINED3DERR_INVALIDCALL;
4647     }
4648     for (j = 0; j < 256; ++j) {
4649         This->palettes[PaletteNumber][j].peRed   = pEntries[j].peRed;
4650         This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4651         This->palettes[PaletteNumber][j].peBlue  = pEntries[j].peBlue;
4652         This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4653     }
4654     TRACE("(%p) : returning\n", This);
4655     return WINED3D_OK;
4656 }
4657
4658 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4659     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4660     int j;
4661     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4662     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4663         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4664         return WINED3DERR_INVALIDCALL;
4665     }
4666     for (j = 0; j < 256; ++j) {
4667         pEntries[j].peRed   = This->palettes[PaletteNumber][j].peRed;
4668         pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4669         pEntries[j].peBlue  = This->palettes[PaletteNumber][j].peBlue;
4670         pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4671     }
4672     TRACE("(%p) : returning\n", This);
4673     return WINED3D_OK;
4674 }
4675
4676 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4677     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4678     TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4679     if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4680         WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4681         return WINED3DERR_INVALIDCALL;
4682     }
4683     /*TODO: stateblocks */
4684     This->currentPalette = PaletteNumber;
4685     TRACE("(%p) : returning\n", This);
4686     return WINED3D_OK;
4687 }
4688
4689 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4690     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4691     if (PaletteNumber == NULL) {
4692         WARN("(%p) : returning Invalid Call\n", This);
4693         return WINED3DERR_INVALIDCALL;
4694     }
4695     /*TODO: stateblocks */
4696     *PaletteNumber = This->currentPalette;
4697     TRACE("(%p) : returning  %u\n", This, *PaletteNumber);
4698     return WINED3D_OK;
4699 }
4700
4701 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4702     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4703     static BOOL showFixmes = TRUE;
4704     if (showFixmes) {
4705         FIXME("(%p) : stub\n", This);
4706         showFixmes = FALSE;
4707     }
4708
4709     This->softwareVertexProcessing = bSoftware;
4710     return WINED3D_OK;
4711 }
4712
4713
4714 static BOOL     WINAPI  IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4715     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4716     static BOOL showFixmes = TRUE;
4717     if (showFixmes) {
4718         FIXME("(%p) : stub\n", This);
4719         showFixmes = FALSE;
4720     }
4721     return This->softwareVertexProcessing;
4722 }
4723
4724
4725 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
4726     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4727     IWineD3DSwapChain *swapChain;
4728     HRESULT hr;
4729
4730     TRACE("(%p) :  SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4731
4732     hr = IWineD3DDeviceImpl_GetSwapChain(iface,  iSwapChain, (IWineD3DSwapChain **)&swapChain);
4733     if(hr == WINED3D_OK){
4734         hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4735         IWineD3DSwapChain_Release(swapChain);
4736     }else{
4737         FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
4738     }
4739     return hr;
4740 }
4741
4742
4743 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4744     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4745     static BOOL showfixmes = TRUE;
4746     if(nSegments != 0.0f) {
4747         if( showfixmes) {
4748             FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4749             showfixmes = FALSE;
4750         }
4751     }
4752     return WINED3D_OK;
4753 }
4754
4755 static float    WINAPI  IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4756     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4757     static BOOL showfixmes = TRUE;
4758     if( showfixmes) {
4759         FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4760         showfixmes = FALSE;
4761     }
4762     return 0.0f;
4763 }
4764
4765 static HRESULT  WINAPI  IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4766     IWineD3DDeviceImpl  *This         = (IWineD3DDeviceImpl *) iface;
4767     /** TODO: remove casts to IWineD3DSurfaceImpl
4768      *       NOTE: move code to surface to accomplish this
4769       ****************************************/
4770     IWineD3DSurfaceImpl *pSrcSurface  = (IWineD3DSurfaceImpl *)pSourceSurface;
4771     int srcWidth, srcHeight;
4772     unsigned int  srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4773     WINED3DFORMAT destFormat, srcFormat;
4774     UINT          destSize;
4775     int srcLeft, destLeft, destTop;
4776     WINED3DPOOL       srcPool, destPool;
4777     int offset    = 0;
4778     int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4779     glDescriptor *glDescription = NULL;
4780
4781     WINED3DSURFACE_DESC  winedesc;
4782
4783     TRACE("(%p) : Source (%p)  Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
4784     memset(&winedesc, 0, sizeof(winedesc));
4785     winedesc.Width  = &srcSurfaceWidth;
4786     winedesc.Height = &srcSurfaceHeight;
4787     winedesc.Pool   = &srcPool;
4788     winedesc.Format = &srcFormat;
4789
4790     IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4791
4792     winedesc.Width  = &destSurfaceWidth;
4793     winedesc.Height = &destSurfaceHeight;
4794     winedesc.Pool   = &destPool;
4795     winedesc.Format = &destFormat;
4796     winedesc.Size   = &destSize;
4797
4798     IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4799
4800     if(srcPool != WINED3DPOOL_SYSTEMMEM  || destPool != WINED3DPOOL_DEFAULT){
4801         WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
4802         return WINED3DERR_INVALIDCALL;
4803     }
4804
4805     if (destFormat == WINED3DFMT_UNKNOWN) {
4806         TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
4807         IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
4808
4809         /* Get the update surface description */
4810         IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4811     }
4812
4813     ENTER_GL();
4814
4815     ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
4816
4817     if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4818         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
4819         checkGLcall("glActiveTextureARB");
4820     }
4821
4822     /* Make sure the surface is loaded and up to date */
4823     IWineD3DSurface_PreLoad(pDestinationSurface);
4824
4825     IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4826
4827     /* this needs to be done in lines if the sourceRect != the sourceWidth */
4828     srcWidth   = pSourceRect ? pSourceRect->right - pSourceRect->left   : srcSurfaceWidth;
4829     srcHeight  = pSourceRect ? pSourceRect->bottom - pSourceRect->top   : srcSurfaceHeight;
4830     srcLeft    = pSourceRect ? pSourceRect->left : 0;
4831     destLeft   = pDestPoint  ? pDestPoint->x : 0;
4832     destTop    = pDestPoint  ? pDestPoint->y : 0;
4833
4834
4835     /* This function doesn't support compressed textures
4836     the pitch is just bytesPerPixel * width */
4837     if(srcWidth != srcSurfaceWidth  || srcLeft ){
4838         rowoffset = srcSurfaceWidth * pSrcSurface->bytesPerPixel;
4839         offset   += srcLeft * pSrcSurface->bytesPerPixel;
4840         /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4841     }
4842     /* TODO DXT formats */
4843
4844     if(pSourceRect != NULL && pSourceRect->top != 0){
4845        offset +=  pSourceRect->top * srcSurfaceWidth * pSrcSurface->bytesPerPixel;
4846     }
4847     TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4848     ,This
4849     ,glDescription->level
4850     ,destLeft
4851     ,destTop
4852     ,srcWidth
4853     ,srcHeight
4854     ,glDescription->glFormat
4855     ,glDescription->glType
4856     ,IWineD3DSurface_GetData(pSourceSurface)
4857     );
4858
4859     /* Sanity check */
4860     if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4861
4862         /* need to lock the surface to get the data */
4863         FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4864     }
4865
4866     /* TODO: Cube and volume support */
4867     if(rowoffset != 0){
4868         /* not a whole row so we have to do it a line at a time */
4869         int j;
4870
4871         /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4872         const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4873
4874         for(j = destTop ; j < (srcHeight + destTop) ; j++){
4875
4876                 glTexSubImage2D(glDescription->target
4877                     ,glDescription->level
4878                     ,destLeft
4879                     ,j
4880                     ,srcWidth
4881                     ,1
4882                     ,glDescription->glFormat
4883                     ,glDescription->glType
4884                     ,data /* could be quicker using */
4885                 );
4886             data += rowoffset;
4887         }
4888
4889     } else { /* Full width, so just write out the whole texture */
4890
4891         if (WINED3DFMT_DXT1 == destFormat ||
4892             WINED3DFMT_DXT2 == destFormat ||
4893             WINED3DFMT_DXT3 == destFormat ||
4894             WINED3DFMT_DXT4 == destFormat ||
4895             WINED3DFMT_DXT5 == destFormat) {
4896             if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4897                 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4898                     /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
4899                     FIXME("Updating part of a compressed texture is not supported at the moment\n");
4900                 } if (destFormat != srcFormat) {
4901                     FIXME("Updating mixed format compressed texture is not curretly support\n");
4902                 } else {
4903                     GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4904                                                         glDescription->level,
4905                                                         glDescription->glFormatInternal,
4906                                                         srcWidth,
4907                                                         srcHeight,
4908                                                         0,
4909                                                         destSize,
4910                                                         IWineD3DSurface_GetData(pSourceSurface));
4911                 }
4912             } else {
4913                 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4914             }
4915
4916
4917         } else {
4918             glTexSubImage2D(glDescription->target
4919                     ,glDescription->level
4920                     ,destLeft
4921                     ,destTop
4922                     ,srcWidth
4923                     ,srcHeight
4924                     ,glDescription->glFormat
4925                     ,glDescription->glType
4926                     ,IWineD3DSurface_GetData(pSourceSurface)
4927                 );
4928         }
4929      }
4930     checkGLcall("glTexSubImage2D");
4931
4932     LEAVE_GL();
4933
4934     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags &= ~SFLAG_INSYSMEM;
4935     ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_INTEXTURE;
4936     IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
4937
4938     return WINED3D_OK;
4939 }
4940
4941 /* Implementation details at http://developer.nvidia.com/attach/6494
4942 and
4943 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4944 hmm.. no longer supported use
4945 OpenGL evaluators or  tessellate surfaces within your application.
4946 */
4947
4948 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4949 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
4950     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4951     TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
4952     FIXME("(%p) : Stub\n", This);
4953     return WINED3D_OK;
4954
4955 }
4956
4957 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4958 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
4959     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4960     TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
4961     FIXME("(%p) : Stub\n", This);
4962     return WINED3D_OK;
4963 }
4964
4965 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4966     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4967     TRACE("(%p) Handle(%d)\n", This, Handle);
4968     FIXME("(%p) : Stub\n", This);
4969     return WINED3D_OK;
4970 }
4971
4972 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
4973     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4974     IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
4975     DDBLTFX BltFx;
4976     TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
4977
4978     if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
4979         FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
4980         return WINED3DERR_INVALIDCALL;
4981     }
4982
4983     /* Just forward this to the DirectDraw blitting engine */
4984     memset(&BltFx, 0, sizeof(BltFx));
4985     BltFx.dwSize = sizeof(BltFx);
4986     BltFx.u5.dwFillColor = color;
4987     return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx, WINED3DTEXF_NONE);
4988 }
4989
4990 /* rendertarget and deptth stencil functions */
4991 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
4992     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4993
4994     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
4995         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
4996         return WINED3DERR_INVALIDCALL;
4997     }
4998
4999     *ppRenderTarget = This->render_targets[RenderTargetIndex];
5000     TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5001     /* Note inc ref on returned surface */
5002     if(*ppRenderTarget != NULL)
5003         IWineD3DSurface_AddRef(*ppRenderTarget);
5004     return WINED3D_OK;
5005 }
5006
5007 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
5008     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5009     IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
5010     IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
5011     IWineD3DSwapChainImpl *Swapchain;
5012     HRESULT hr;
5013
5014     TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
5015
5016     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
5017     if(hr != WINED3D_OK) {
5018         ERR("Can't get the swapchain\n");
5019         return hr;
5020     }
5021
5022     /* Make sure to release the swapchain */
5023     IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
5024
5025     if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
5026         ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5027         return WINED3DERR_INVALIDCALL;
5028     }
5029     else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
5030         ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
5031         return WINED3DERR_INVALIDCALL;
5032     }
5033
5034     if(Swapchain->frontBuffer != Front) {
5035         TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
5036
5037         if(Swapchain->frontBuffer)
5038             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
5039         Swapchain->frontBuffer = Front;
5040
5041         if(Swapchain->frontBuffer) {
5042             IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
5043         }
5044     }
5045
5046     if(Back && !Swapchain->backBuffer) {
5047         /* We need memory for the back buffer array - only one back buffer this way */
5048         Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
5049         if(!Swapchain->backBuffer) {
5050             ERR("Out of memory\n");
5051             return E_OUTOFMEMORY;
5052         }
5053     }
5054
5055     if(Swapchain->backBuffer[0] != Back) {
5056         TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
5057
5058         /* What to do about the context here in the case of multithreading? Not sure.
5059          * This function is called by IDirect3D7::CreateDevice so in theory its initialization code
5060          */
5061         ENTER_GL();
5062         if(!Swapchain->backBuffer[0]) {
5063             /* GL was told to draw to the front buffer at creation,
5064              * undo that
5065              */
5066             glDrawBuffer(GL_BACK);
5067             checkGLcall("glDrawBuffer(GL_BACK)");
5068             /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
5069             Swapchain->presentParms.BackBufferCount = 1;
5070         } else if (!Back) {
5071             /* That makes problems - disable for now */
5072             /* glDrawBuffer(GL_FRONT); */
5073             checkGLcall("glDrawBuffer(GL_FRONT)");
5074             /* We have lost our back buffer, set this to 0 to avoid confusing other code */
5075             Swapchain->presentParms.BackBufferCount = 0;
5076         }
5077         LEAVE_GL();
5078
5079         if(Swapchain->backBuffer[0])
5080             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
5081         Swapchain->backBuffer[0] = Back;
5082
5083         if(Swapchain->backBuffer[0]) {
5084             IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
5085         } else {
5086             HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
5087         }
5088
5089     }
5090
5091     return WINED3D_OK;
5092 }
5093
5094 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5095     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5096     *ppZStencilSurface = This->depthStencilBuffer;
5097     TRACE("(%p) : zStencilSurface  returning %p\n", This,  *ppZStencilSurface);
5098
5099     if(*ppZStencilSurface != NULL) {
5100         /* Note inc ref on returned surface */
5101         IWineD3DSurface_AddRef(*ppZStencilSurface);
5102     }
5103     return WINED3D_OK;
5104 }
5105
5106 static void bind_fbo(IWineD3DDevice *iface, GLenum target, GLuint *fbo) {
5107     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5108
5109     if (!*fbo) {
5110         GL_EXTCALL(glGenFramebuffersEXT(1, fbo));
5111         checkGLcall("glGenFramebuffersEXT()");
5112     }
5113     GL_EXTCALL(glBindFramebufferEXT(target, *fbo));
5114     checkGLcall("glBindFramebuffer()");
5115 }
5116
5117 /* TODO: Handle stencil attachments */
5118 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5119     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5120     IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5121
5122     TRACE("Set depth stencil to %p\n", depth_stencil);
5123
5124     if (depth_stencil_impl) {
5125         if (depth_stencil_impl->current_renderbuffer) {
5126             GL_EXTCALL(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depth_stencil_impl->current_renderbuffer->id));
5127             checkGLcall("glFramebufferRenderbufferEXT()");
5128         } else {
5129             GLenum texttarget, target;
5130             GLint old_binding = 0;
5131
5132             texttarget = depth_stencil_impl->glDescription.target;
5133             target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5134             glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5135
5136             IWineD3DSurface_PreLoad(depth_stencil);
5137
5138             glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5139             glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5140             glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5141             glBindTexture(target, old_binding);
5142
5143             GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5144             checkGLcall("glFramebufferTexture2DEXT()");
5145         }
5146     } else {
5147         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5148         checkGLcall("glFramebufferTexture2DEXT()");
5149     }
5150 }
5151
5152 static void attach_surface_fbo(IWineD3DDeviceImpl *This, GLenum fbo_target, DWORD idx, IWineD3DSurface *surface) {
5153     const IWineD3DSurfaceImpl *surface_impl = (IWineD3DSurfaceImpl *)surface;
5154     GLenum texttarget, target;
5155     GLint old_binding;
5156
5157     texttarget = surface_impl->glDescription.target;
5158     target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5159     glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5160
5161     IWineD3DSurface_PreLoad(surface);
5162
5163     glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5164     glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5165     glBindTexture(target, old_binding);
5166
5167     GL_EXTCALL(glFramebufferTexture2DEXT(fbo_target, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, surface_impl->glDescription.textureName, 0));
5168
5169     checkGLcall("attach_surface_fbo");
5170 }
5171
5172 static void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5173     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5174     IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5175
5176     TRACE("Set render target %u to %p\n", idx, render_target);
5177
5178     if (rtimpl) {
5179         attach_surface_fbo(This, GL_FRAMEBUFFER_EXT, idx, render_target);
5180         This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5181     } else {
5182         GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5183         checkGLcall("glFramebufferTexture2DEXT()");
5184
5185         This->draw_buffers[idx] = GL_NONE;
5186     }
5187 }
5188
5189 static void check_fbo_status(IWineD3DDevice *iface) {
5190     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5191     GLenum status;
5192
5193     status = GL_EXTCALL(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
5194     switch(status) {
5195         case GL_FRAMEBUFFER_COMPLETE_EXT: TRACE("FBO complete.\n"); break;
5196         default: FIXME("FBO status %#x.\n", status); break;
5197     }
5198 }
5199
5200 static BOOL depth_mismatch_fbo(IWineD3DDevice *iface) {
5201     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5202     IWineD3DSurfaceImpl *rt_impl = (IWineD3DSurfaceImpl *)This->render_targets[0];
5203     IWineD3DSurfaceImpl *ds_impl = (IWineD3DSurfaceImpl *)This->stencilBufferTarget;
5204
5205     if (!ds_impl) return FALSE;
5206
5207     if (ds_impl->current_renderbuffer) {
5208         return (rt_impl->pow2Width != ds_impl->current_renderbuffer->width ||
5209                 rt_impl->pow2Height != ds_impl->current_renderbuffer->height);
5210     }
5211
5212     return (rt_impl->pow2Width != ds_impl->pow2Width ||
5213             rt_impl->pow2Height != ds_impl->pow2Height);
5214 }
5215
5216 void apply_fbo_state(IWineD3DDevice *iface) {
5217     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5218     unsigned int i;
5219
5220     if (This->render_offscreen) {
5221         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5222
5223         /* Apply render targets */
5224         for (i = 0; i < GL_LIMITS(buffers); ++i) {
5225             IWineD3DSurface *render_target = This->render_targets[i];
5226             if (This->fbo_color_attachments[i] != render_target) {
5227                 set_render_target_fbo(iface, i, render_target);
5228                 This->fbo_color_attachments[i] = render_target;
5229             }
5230         }
5231
5232         /* Apply depth targets */
5233         if (This->fbo_depth_attachment != This->stencilBufferTarget || depth_mismatch_fbo(iface)) {
5234             unsigned int w = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Width;
5235             unsigned int h = ((IWineD3DSurfaceImpl *)This->render_targets[0])->pow2Height;
5236
5237             if (This->stencilBufferTarget) {
5238                 surface_set_compatible_renderbuffer(This->stencilBufferTarget, w, h);
5239             }
5240             set_depth_stencil_fbo(iface, This->stencilBufferTarget);
5241             This->fbo_depth_attachment = This->stencilBufferTarget;
5242         }
5243
5244         if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5245             GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5246             checkGLcall("glDrawBuffers()");
5247         }
5248     } else {
5249         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5250     }
5251
5252     check_fbo_status(iface);
5253 }
5254
5255 static BOOL is_onscreen(IWineD3DSurface *target) {
5256     HRESULT hr;
5257     void *tmp;
5258
5259     hr = IWineD3DSurface_GetContainer(target, &IID_IWineD3DSwapChain, &tmp);
5260     if (SUCCEEDED(hr)) {
5261         IWineD3DSwapChain_Release((IUnknown *)tmp);
5262         return TRUE;
5263     }
5264
5265     return FALSE;
5266 }
5267
5268 void stretch_rect_fbo(IWineD3DDevice *iface, IWineD3DSurface *src_surface, const WINED3DRECT *src_rect,
5269         IWineD3DSurface *dst_surface, const WINED3DRECT *dst_rect, const WINED3DTEXTUREFILTERTYPE filter, BOOL flip) {
5270     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5271     GLbitfield mask = GL_COLOR_BUFFER_BIT; /* TODO: Support blitting depth/stencil surfaces */
5272     GLenum gl_filter;
5273
5274     TRACE("(%p) : src_surface %p, src_rect %p, dst_surface %p, dst_rect %p, filter %s (0x%08x)\n",
5275             This, src_surface, src_rect, dst_surface, dst_rect, debug_d3dtexturefiltertype(filter), filter);
5276
5277     switch (filter) {
5278         case WINED3DTEXF_LINEAR:
5279             gl_filter = GL_LINEAR;
5280             break;
5281
5282         default:
5283             FIXME("Unsupported filter mode %s (0x%08x)\n", debug_d3dtexturefiltertype(filter), filter);
5284         case WINED3DTEXF_NONE:
5285         case WINED3DTEXF_POINT:
5286             gl_filter = GL_NEAREST;
5287             break;
5288     }
5289
5290     /* Attach src surface to src fbo */
5291     if (is_onscreen(src_surface)) {
5292         GL_EXTCALL(glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0));
5293         flip = !flip;
5294     } else {
5295         IWineD3DSurface_PreLoad(src_surface);
5296         bind_fbo(iface, GL_READ_FRAMEBUFFER_EXT, &This->src_fbo);
5297         attach_surface_fbo(This, GL_READ_FRAMEBUFFER_EXT, 0, src_surface);
5298     }
5299
5300     /* Attach dst surface to dst fbo */
5301     if (is_onscreen(dst_surface)) {
5302         GL_EXTCALL(glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0));
5303         flip = !flip;
5304     } else {
5305         IWineD3DSurface_PreLoad(dst_surface);
5306         bind_fbo(iface, GL_DRAW_FRAMEBUFFER_EXT, &This->dst_fbo);
5307         attach_surface_fbo(This, GL_DRAW_FRAMEBUFFER_EXT, 0, dst_surface);
5308     }
5309
5310     if (flip) {
5311         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
5312                 dst_rect->x1, dst_rect->y2, dst_rect->x2, dst_rect->y1, mask, gl_filter));
5313     } else {
5314         GL_EXTCALL(glBlitFramebufferEXT(src_rect->x1, src_rect->y1, src_rect->x2, src_rect->y2,
5315                 dst_rect->x1, dst_rect->y1, dst_rect->x2, dst_rect->y2, mask, gl_filter));
5316     }
5317
5318     if (This->render_offscreen) {
5319         bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5320     } else {
5321         GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5322         checkGLcall("glBindFramebuffer()");
5323     }
5324 }
5325
5326 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5327     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5328     WINED3DVIEWPORT viewport;
5329
5330     TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5331
5332     if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5333         ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5334         return WINED3DERR_INVALIDCALL;
5335     }
5336
5337     /* MSDN says that null disables the render target
5338     but a device must always be associated with a render target
5339     nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5340
5341     see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5342     for more details
5343     */
5344     if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5345         FIXME("Trying to set render target 0 to NULL\n");
5346         return WINED3DERR_INVALIDCALL;
5347     }
5348     if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5349         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);
5350         return WINED3DERR_INVALIDCALL;
5351     }
5352
5353     /* If we are trying to set what we already have, don't bother */
5354     if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5355         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5356         return WINED3D_OK;
5357     }
5358     if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5359     if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5360     This->render_targets[RenderTargetIndex] = pRenderTarget;
5361
5362     /* Render target 0 is special */
5363     if(RenderTargetIndex == 0) {
5364         /* Finally, reset the viewport as the MSDN states. */
5365         viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5366         viewport.Width  = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5367         viewport.X      = 0;
5368         viewport.Y      = 0;
5369         viewport.MaxZ   = 1.0f;
5370         viewport.MinZ   = 0.0f;
5371         IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5372         /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
5373          * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
5374          */
5375         IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
5376
5377         /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
5378          * ctx properly.
5379          * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
5380          * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
5381          */
5382         ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
5383     }
5384     return WINED3D_OK;
5385 }
5386
5387 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5388     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5389     HRESULT  hr = WINED3D_OK;
5390     IWineD3DSurface *tmp;
5391
5392     TRACE("(%p) Swapping z-buffer\n",This);
5393
5394     if (pNewZStencil == This->stencilBufferTarget) {
5395         TRACE("Trying to do a NOP SetRenderTarget operation\n");
5396     } else {
5397         /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5398         * depending on the renter target implementation being used.
5399         * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5400         * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5401         * stencil buffer and incure an extra memory overhead
5402          ******************************************************/
5403
5404         tmp = This->stencilBufferTarget;
5405         This->stencilBufferTarget = pNewZStencil;
5406         This->depth_copy_state = WINED3D_DCS_NO_COPY;
5407         /* should we be calling the parent or the wined3d surface? */
5408         if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5409         if (NULL != tmp) IWineD3DSurface_Release(tmp);
5410         hr = WINED3D_OK;
5411
5412         if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
5413             /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5414             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
5415             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
5416             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
5417         }
5418     }
5419
5420     return hr;
5421 }
5422
5423 static HRESULT  WINAPI  IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5424                                                         UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5425     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5426     /* TODO: the use of Impl is deprecated. */
5427     IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5428
5429     TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5430
5431     /* some basic validation checks */
5432     if(This->cursorTexture) {
5433         ENTER_GL();
5434         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5435         glDeleteTextures(1, &This->cursorTexture);
5436         LEAVE_GL();
5437         This->cursorTexture = 0;
5438     }
5439
5440     if(pCursorBitmap) {
5441         WINED3DLOCKED_RECT rect;
5442
5443         /* MSDN: Cursor must be A8R8G8B8 */
5444         if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5445             ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5446             return WINED3DERR_INVALIDCALL;
5447         }
5448
5449         /* MSDN: Cursor must be smaller than the display mode */
5450         if(pSur->currentDesc.Width > This->ddraw_width ||
5451            pSur->currentDesc.Height > This->ddraw_height) {
5452             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);
5453             return WINED3DERR_INVALIDCALL;
5454         }
5455
5456         /* TODO: MSDN: Cursor sizes must be a power of 2 */
5457
5458         /* Do not store the surface's pointer because the application may release
5459          * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
5460          * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
5461          */
5462         This->cursorWidth = pSur->currentDesc.Width;
5463         This->cursorHeight = pSur->currentDesc.Height;
5464         if (SUCCEEDED(IWineD3DSurface_LockRect(pCursorBitmap, &rect, NULL, WINED3DLOCK_READONLY)))
5465         {
5466             const PixelFormatDesc *tableEntry = getFormatDescEntry(WINED3DFMT_A8R8G8B8);
5467             char *mem, *bits = (char *)rect.pBits;
5468             GLint intfmt = tableEntry->glInternal;
5469             GLint format = tableEntry->glFormat;
5470             GLint type = tableEntry->glType;
5471             INT height = This->cursorHeight;
5472             INT width = This->cursorWidth;
5473             INT bpp = tableEntry->bpp;
5474             INT i;
5475
5476             /* Reformat the texture memory (pitch and width can be different) */
5477             mem = HeapAlloc(GetProcessHeap(), 0, width * height * bpp);
5478             for(i = 0; i < height; i++)
5479                 memcpy(&mem[width * bpp * i], &bits[rect.Pitch * i], width * bpp);
5480             IWineD3DSurface_UnlockRect(pCursorBitmap);
5481             ENTER_GL();
5482             /* Make sure that a proper texture unit is selected */
5483             if (GL_SUPPORT(ARB_MULTITEXTURE)) {
5484                 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
5485                 checkGLcall("glActiveTextureARB");
5486             }
5487             IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
5488             /* Create a new cursor texture */
5489             glGenTextures(1, &This->cursorTexture);
5490             checkGLcall("glGenTextures");
5491             glBindTexture(GL_TEXTURE_2D, This->cursorTexture);
5492             checkGLcall("glBindTexture");
5493             /* Copy the bitmap memory into the cursor texture */
5494             glTexImage2D(GL_TEXTURE_2D, 0, intfmt, width, height, 0, format, type, mem);
5495             HeapFree(GetProcessHeap(), 0, mem);
5496             checkGLcall("glTexImage2D");
5497             LEAVE_GL();
5498         }
5499         else
5500         {
5501             FIXME("A cursor texture was not returned.\n");
5502             This->cursorTexture = 0;
5503         }
5504
5505     }
5506
5507     This->xHotSpot = XHotSpot;
5508     This->yHotSpot = YHotSpot;
5509     return WINED3D_OK;
5510 }
5511
5512 static void     WINAPI  IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5513     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5514     TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5515
5516     This->xScreenSpace = XScreenSpace;
5517     This->yScreenSpace = YScreenSpace;
5518
5519     return;
5520
5521 }
5522
5523 static BOOL     WINAPI  IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5524     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5525     BOOL oldVisible = This->bCursorVisible;
5526     POINT pt;
5527
5528     TRACE("(%p) : visible(%d)\n", This, bShow);
5529
5530     if(This->cursorTexture)
5531         This->bCursorVisible = bShow;
5532     /*
5533      * When ShowCursor is first called it should make the cursor appear at the OS's last
5534      * known cursor position.  Because of this, some applications just repetitively call
5535      * ShowCursor in order to update the cursor's position.  This behavior is undocumented.
5536      */
5537     GetCursorPos(&pt);
5538     This->xScreenSpace = pt.x;
5539     This->yScreenSpace = pt.y;
5540
5541     return oldVisible;
5542 }
5543
5544 static HRESULT  WINAPI  IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5545     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5546     TRACE("(%p) : state (%u)\n", This, This->state);
5547     /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
5548     switch (This->state) {
5549     case WINED3D_OK:
5550         return WINED3D_OK;
5551     case WINED3DERR_DEVICELOST:
5552         {
5553             ResourceList *resourceList  = This->resources;
5554             while (NULL != resourceList) {
5555                 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
5556                 return WINED3DERR_DEVICENOTRESET;
5557                 resourceList = resourceList->next;
5558             }
5559             return WINED3DERR_DEVICELOST;
5560         }
5561     case WINED3DERR_DRIVERINTERNALERROR:
5562         return WINED3DERR_DRIVERINTERNALERROR;
5563     }
5564
5565     /* Unknown state */
5566     return WINED3DERR_DRIVERINTERNALERROR;
5567 }
5568
5569
5570 static HRESULT  WINAPI  IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5571     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5572     /** FIXME: Resource tracking needs to be done,
5573     * The closes we can do to this is set the priorities of all managed textures low
5574     * and then reset them.
5575      ***********************************************************/
5576     FIXME("(%p) : stub\n", This);
5577     return WINED3D_OK;
5578 }
5579
5580 static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5581     IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
5582
5583     /* Reallocate proper memory for the front and back buffer and adjust their sizes */
5584     if(surface->Flags & SFLAG_DIBSECTION) {
5585         /* Release the DC */
5586         SelectObject(surface->hDC, surface->dib.holdbitmap);
5587         DeleteDC(surface->hDC);
5588         /* Release the DIB section */
5589         DeleteObject(surface->dib.DIBsection);
5590         surface->dib.bitmap_data = NULL;
5591         surface->resource.allocatedMemory = NULL;
5592         surface->Flags &= ~SFLAG_DIBSECTION;
5593     }
5594     surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
5595     surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
5596     if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
5597         surface->pow2Width = pPresentationParameters->BackBufferWidth;
5598         surface->pow2Height = pPresentationParameters->BackBufferHeight;
5599     } else {
5600         surface->pow2Width = surface->pow2Height = 1;
5601         while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
5602         while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
5603     }
5604     if(surface->glDescription.textureName) {
5605         ENTER_GL();
5606         ActivateContext(This, This->lastActiveRenderTarget, CTXUSAGE_RESOURCELOAD);
5607         glDeleteTextures(1, &surface->glDescription.textureName);
5608         LEAVE_GL();
5609         surface->glDescription.textureName = 0;
5610         surface->Flags &= ~SFLAG_CLIENT;
5611     }
5612     if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
5613        surface->pow2Height != pPresentationParameters->BackBufferHeight) {
5614         surface->Flags |= SFLAG_NONPOW2;
5615     } else  {
5616         surface->Flags &= ~SFLAG_NONPOW2;
5617     }
5618     HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
5619     surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
5620 }
5621
5622 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5623     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5624     IWineD3DSwapChainImpl *swapchain;
5625     HRESULT hr;
5626     BOOL DisplayModeChanged = FALSE;
5627     WINED3DDISPLAYMODE mode;
5628     TRACE("(%p)\n", This);
5629
5630     hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
5631     if(FAILED(hr)) {
5632         ERR("Failed to get the first implicit swapchain\n");
5633         return hr;
5634     }
5635
5636     /* Is it necessary to recreate the gl context? Actually every setting can be changed
5637      * on an existing gl context, so there's no real need for recreation.
5638      *
5639      * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
5640      *
5641      * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
5642      */
5643     TRACE("New params:\n");
5644     TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
5645     TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
5646     TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
5647     TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
5648     TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
5649     TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
5650     TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
5651     TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
5652     TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
5653     TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
5654     TRACE("Flags = %08x\n", pPresentationParameters->Flags);
5655     TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
5656     TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
5657
5658     /* No special treatment of these parameters. Just store them */
5659     swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
5660     swapchain->presentParms.Flags = pPresentationParameters->Flags;
5661     swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
5662     swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
5663
5664     /* What to do about these? */
5665     if(pPresentationParameters->BackBufferCount != 0 &&
5666         pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
5667         ERR("Cannot change the back buffer count yet\n");
5668     }
5669     if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
5670         pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
5671         ERR("Cannot change the back buffer format yet\n");
5672     }
5673     if(pPresentationParameters->hDeviceWindow != NULL &&
5674         pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
5675         ERR("Cannot change the device window yet\n");
5676     }
5677     if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
5678         ERR("What do do about a changed auto depth stencil parameter?\n");
5679     }
5680
5681     if(pPresentationParameters->Windowed) {
5682         mode.Width = swapchain->orig_width;
5683         mode.Height = swapchain->orig_height;
5684         mode.RefreshRate = 0;
5685         mode.Format = swapchain->presentParms.BackBufferFormat;
5686     } else {
5687         mode.Width = pPresentationParameters->BackBufferWidth;
5688         mode.Height = pPresentationParameters->BackBufferHeight;
5689         mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
5690         mode.Format = swapchain->presentParms.BackBufferFormat;
5691     }
5692
5693     /* Should Width == 800 && Height == 0 set 800x600? */
5694     if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
5695        (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
5696         pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
5697     {
5698         WINED3DVIEWPORT vp;
5699         int i;
5700
5701         vp.X = 0;
5702         vp.Y = 0;
5703         vp.Width = pPresentationParameters->BackBufferWidth;
5704         vp.Height = pPresentationParameters->BackBufferHeight;
5705         vp.MinZ = 0;
5706         vp.MaxZ = 1;
5707
5708         if(!pPresentationParameters->Windowed) {
5709             DisplayModeChanged = TRUE;
5710         }
5711         swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
5712         swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
5713
5714         updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
5715         for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
5716             updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
5717         }
5718
5719         /* Now set the new viewport */
5720         IWineD3DDevice_SetViewport(iface, &vp);
5721     }
5722
5723     if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
5724        (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
5725         DisplayModeChanged) {
5726
5727         /* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */
5728         if(!pPresentationParameters->Windowed) {
5729             IWineD3DDevice_SetFullscreen(iface, TRUE);
5730         }
5731
5732         IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
5733
5734         /* Switching out of fullscreen mode? First set the original res, then change the window */
5735         if(pPresentationParameters->Windowed) {
5736             IWineD3DDevice_SetFullscreen(iface, FALSE);
5737         }
5738         swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
5739     }
5740
5741     IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
5742     return WINED3D_OK;
5743 }
5744
5745 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5746     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5747     /** FIXME: always true at the moment **/
5748     if(!bEnableDialogs) {
5749         FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5750     }
5751     return WINED3D_OK;
5752 }
5753
5754
5755 static HRESULT  WINAPI  IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
5756     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5757     TRACE("(%p) : pParameters %p\n", This, pParameters);
5758
5759     *pParameters = This->createParms;
5760     return WINED3D_OK;
5761 }
5762
5763 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
5764     IWineD3DSwapChain *swapchain;
5765     HRESULT hrc = WINED3D_OK;
5766
5767     TRACE("Relaying  to swapchain\n");
5768
5769     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5770         IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
5771         IWineD3DSwapChain_Release(swapchain);
5772     }
5773     return;
5774 }
5775
5776 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
5777     IWineD3DSwapChain *swapchain;
5778     HRESULT hrc = WINED3D_OK;
5779
5780     TRACE("Relaying  to swapchain\n");
5781
5782     if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5783         hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5784         IWineD3DSwapChain_Release(swapchain);
5785     }
5786     return;
5787 }
5788
5789
5790 /** ********************************************************
5791 *   Notification functions
5792 ** ********************************************************/
5793 /** This function must be called in the release of a resource when ref == 0,
5794 * the contents of resource must still be correct,
5795 * any handels to other resource held by the caller must be closed
5796 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5797  *****************************************************/
5798 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5799     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5800     ResourceList* resourceList;
5801
5802     TRACE("(%p) : resource %p\n", This, resource);
5803 #if 0
5804     EnterCriticalSection(&resourceStoreCriticalSection);
5805 #endif
5806     /* add a new texture to the frot of the linked list */
5807     resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5808     resourceList->resource = resource;
5809
5810     /* Get the old head */
5811     resourceList->next = This->resources;
5812
5813     This->resources = resourceList;
5814     TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5815
5816 #if 0
5817     LeaveCriticalSection(&resourceStoreCriticalSection);
5818 #endif
5819     return;
5820 }
5821
5822 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5823     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5824     ResourceList* resourceList = NULL;
5825     ResourceList* previousResourceList = NULL;
5826     
5827     TRACE("(%p) : resource %p\n", This, resource);
5828
5829 #if 0
5830     EnterCriticalSection(&resourceStoreCriticalSection);
5831 #endif
5832     resourceList = This->resources;
5833
5834     while (resourceList != NULL) {
5835         if(resourceList->resource == resource) break;
5836         previousResourceList = resourceList;
5837         resourceList = resourceList->next;
5838     }
5839
5840     if (resourceList == NULL) {
5841         FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5842 #if 0
5843         LeaveCriticalSection(&resourceStoreCriticalSection);
5844 #endif
5845         return;
5846     } else {
5847             TRACE("Found resource  %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5848     }
5849     /* make sure we don't leave a hole in the list */
5850     if (previousResourceList != NULL) {
5851         previousResourceList->next = resourceList->next;
5852     } else {
5853         This->resources = resourceList->next;
5854     }
5855
5856 #if 0
5857     LeaveCriticalSection(&resourceStoreCriticalSection);
5858 #endif
5859     return;
5860 }
5861
5862
5863 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5864     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5865     int counter;
5866
5867     TRACE("(%p) : resource %p\n", This, resource);
5868     switch(IWineD3DResource_GetType(resource)){
5869         /* TODO: check front and back buffers, rendertargets etc..  possibly swapchains? */
5870         case WINED3DRTYPE_SURFACE: {
5871             unsigned int i;
5872
5873             /* Cleanup any FBO attachments */
5874             for (i = 0; i < GL_LIMITS(buffers); ++i) {
5875                 if (This->fbo_color_attachments[i] == (IWineD3DSurface *)resource) {
5876                     bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5877                     set_render_target_fbo(iface, i, NULL);
5878                     This->fbo_color_attachments[i] = NULL;
5879                 }
5880             }
5881             if (This->fbo_depth_attachment == (IWineD3DSurface *)resource) {
5882                 bind_fbo(iface, GL_FRAMEBUFFER_EXT, &This->fbo);
5883                 set_depth_stencil_fbo(iface, NULL);
5884                 This->fbo_depth_attachment = NULL;
5885             }
5886
5887             break;
5888         }
5889
5890         case WINED3DRTYPE_TEXTURE:
5891         case WINED3DRTYPE_CUBETEXTURE:
5892         case WINED3DRTYPE_VOLUMETEXTURE:
5893                 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
5894                     if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5895                         WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5896                         This->stateBlock->textures[counter] = NULL;
5897                     }
5898                     if (This->updateStateBlock != This->stateBlock ){
5899                         if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5900                             WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5901                             This->updateStateBlock->textures[counter] = NULL;
5902                         }
5903                     }
5904                 }
5905         break;
5906         case WINED3DRTYPE_VOLUME:
5907         /* TODO: nothing really? */
5908         break;
5909         case WINED3DRTYPE_VERTEXBUFFER:
5910         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5911         {
5912             int streamNumber;
5913             TRACE("Cleaning up stream pointers\n");
5914
5915             for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5916                 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5917                 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5918                 */
5919                 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5920                     if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5921                         FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5922                         This->updateStateBlock->streamSource[streamNumber] = 0;
5923                         /* Set changed flag? */
5924                     }
5925                 }
5926                 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) */
5927                     if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5928                         TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5929                         This->stateBlock->streamSource[streamNumber] = 0;
5930                     }
5931                 }
5932 #if 0   /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5933                  else { /* This shouldn't happen */
5934                     FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5935                 }
5936 #endif
5937
5938             }
5939         }
5940         break;
5941         case WINED3DRTYPE_INDEXBUFFER:
5942         /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5943         if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5944             if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5945                 This->updateStateBlock->pIndexData =  NULL;
5946             }
5947         }
5948         if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5949             if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5950                 This->stateBlock->pIndexData =  NULL;
5951             }
5952         }
5953
5954         break;
5955         default:
5956         FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
5957         break;
5958     }
5959
5960
5961     /* Remove the resoruce from the resourceStore */
5962     IWineD3DDeviceImpl_RemoveResource(iface, resource);
5963
5964     TRACE("Resource released\n");
5965
5966 }
5967
5968 /**********************************************************
5969  * IWineD3DDevice VTbl follows
5970  **********************************************************/
5971
5972 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5973 {
5974     /*** IUnknown methods ***/
5975     IWineD3DDeviceImpl_QueryInterface,
5976     IWineD3DDeviceImpl_AddRef,
5977     IWineD3DDeviceImpl_Release,
5978     /*** IWineD3DDevice methods ***/
5979     IWineD3DDeviceImpl_GetParent,
5980     /*** Creation methods**/
5981     IWineD3DDeviceImpl_CreateVertexBuffer,
5982     IWineD3DDeviceImpl_CreateIndexBuffer,
5983     IWineD3DDeviceImpl_CreateStateBlock,
5984     IWineD3DDeviceImpl_CreateSurface,
5985     IWineD3DDeviceImpl_CreateTexture,
5986     IWineD3DDeviceImpl_CreateVolumeTexture,
5987     IWineD3DDeviceImpl_CreateVolume,
5988     IWineD3DDeviceImpl_CreateCubeTexture,
5989     IWineD3DDeviceImpl_CreateQuery,
5990     IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5991     IWineD3DDeviceImpl_CreateVertexDeclaration,
5992     IWineD3DDeviceImpl_CreateVertexShader,
5993     IWineD3DDeviceImpl_CreatePixelShader,
5994     IWineD3DDeviceImpl_CreatePalette,
5995     /*** Odd functions **/
5996     IWineD3DDeviceImpl_Init3D,
5997     IWineD3DDeviceImpl_Uninit3D,
5998     IWineD3DDeviceImpl_SetFullscreen,
5999     IWineD3DDeviceImpl_SetMultithreaded,
6000     IWineD3DDeviceImpl_EvictManagedResources,
6001     IWineD3DDeviceImpl_GetAvailableTextureMem,
6002     IWineD3DDeviceImpl_GetBackBuffer,
6003     IWineD3DDeviceImpl_GetCreationParameters,
6004     IWineD3DDeviceImpl_GetDeviceCaps,
6005     IWineD3DDeviceImpl_GetDirect3D,
6006     IWineD3DDeviceImpl_GetDisplayMode,
6007     IWineD3DDeviceImpl_SetDisplayMode,
6008     IWineD3DDeviceImpl_GetHWND,
6009     IWineD3DDeviceImpl_SetHWND,
6010     IWineD3DDeviceImpl_GetNumberOfSwapChains,
6011     IWineD3DDeviceImpl_GetRasterStatus,
6012     IWineD3DDeviceImpl_GetSwapChain,
6013     IWineD3DDeviceImpl_Reset,
6014     IWineD3DDeviceImpl_SetDialogBoxMode,
6015     IWineD3DDeviceImpl_SetCursorProperties,
6016     IWineD3DDeviceImpl_SetCursorPosition,
6017     IWineD3DDeviceImpl_ShowCursor,
6018     IWineD3DDeviceImpl_TestCooperativeLevel,
6019     /*** Getters and setters **/
6020     IWineD3DDeviceImpl_SetClipPlane,
6021     IWineD3DDeviceImpl_GetClipPlane,
6022     IWineD3DDeviceImpl_SetClipStatus,
6023     IWineD3DDeviceImpl_GetClipStatus,
6024     IWineD3DDeviceImpl_SetCurrentTexturePalette,
6025     IWineD3DDeviceImpl_GetCurrentTexturePalette,
6026     IWineD3DDeviceImpl_SetDepthStencilSurface,
6027     IWineD3DDeviceImpl_GetDepthStencilSurface,
6028     IWineD3DDeviceImpl_SetFVF,
6029     IWineD3DDeviceImpl_GetFVF,
6030     IWineD3DDeviceImpl_SetGammaRamp,
6031     IWineD3DDeviceImpl_GetGammaRamp,
6032     IWineD3DDeviceImpl_SetIndices,
6033     IWineD3DDeviceImpl_GetIndices,
6034     IWineD3DDeviceImpl_SetBasevertexIndex,
6035     IWineD3DDeviceImpl_SetLight,
6036     IWineD3DDeviceImpl_GetLight,
6037     IWineD3DDeviceImpl_SetLightEnable,
6038     IWineD3DDeviceImpl_GetLightEnable,
6039     IWineD3DDeviceImpl_SetMaterial,
6040     IWineD3DDeviceImpl_GetMaterial,
6041     IWineD3DDeviceImpl_SetNPatchMode,
6042     IWineD3DDeviceImpl_GetNPatchMode,
6043     IWineD3DDeviceImpl_SetPaletteEntries,
6044     IWineD3DDeviceImpl_GetPaletteEntries,
6045     IWineD3DDeviceImpl_SetPixelShader,
6046     IWineD3DDeviceImpl_GetPixelShader,
6047     IWineD3DDeviceImpl_SetPixelShaderConstantB,
6048     IWineD3DDeviceImpl_GetPixelShaderConstantB,
6049     IWineD3DDeviceImpl_SetPixelShaderConstantI,
6050     IWineD3DDeviceImpl_GetPixelShaderConstantI,
6051     IWineD3DDeviceImpl_SetPixelShaderConstantF,
6052     IWineD3DDeviceImpl_GetPixelShaderConstantF,
6053     IWineD3DDeviceImpl_SetRenderState,
6054     IWineD3DDeviceImpl_GetRenderState,
6055     IWineD3DDeviceImpl_SetRenderTarget,
6056     IWineD3DDeviceImpl_GetRenderTarget,
6057     IWineD3DDeviceImpl_SetFrontBackBuffers,
6058     IWineD3DDeviceImpl_SetSamplerState,
6059     IWineD3DDeviceImpl_GetSamplerState,
6060     IWineD3DDeviceImpl_SetScissorRect,
6061     IWineD3DDeviceImpl_GetScissorRect,
6062     IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6063     IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6064     IWineD3DDeviceImpl_SetStreamSource,
6065     IWineD3DDeviceImpl_GetStreamSource,
6066     IWineD3DDeviceImpl_SetStreamSourceFreq,
6067     IWineD3DDeviceImpl_GetStreamSourceFreq,
6068     IWineD3DDeviceImpl_SetTexture,
6069     IWineD3DDeviceImpl_GetTexture,
6070     IWineD3DDeviceImpl_SetTextureStageState,
6071     IWineD3DDeviceImpl_GetTextureStageState,
6072     IWineD3DDeviceImpl_SetTransform,
6073     IWineD3DDeviceImpl_GetTransform,
6074     IWineD3DDeviceImpl_SetVertexDeclaration,
6075     IWineD3DDeviceImpl_GetVertexDeclaration,
6076     IWineD3DDeviceImpl_SetVertexShader,
6077     IWineD3DDeviceImpl_GetVertexShader,
6078     IWineD3DDeviceImpl_SetVertexShaderConstantB,
6079     IWineD3DDeviceImpl_GetVertexShaderConstantB,
6080     IWineD3DDeviceImpl_SetVertexShaderConstantI,
6081     IWineD3DDeviceImpl_GetVertexShaderConstantI,
6082     IWineD3DDeviceImpl_SetVertexShaderConstantF,
6083     IWineD3DDeviceImpl_GetVertexShaderConstantF,
6084     IWineD3DDeviceImpl_SetViewport,
6085     IWineD3DDeviceImpl_GetViewport,
6086     IWineD3DDeviceImpl_MultiplyTransform,
6087     IWineD3DDeviceImpl_ValidateDevice,
6088     IWineD3DDeviceImpl_ProcessVertices,
6089     /*** State block ***/
6090     IWineD3DDeviceImpl_BeginStateBlock,
6091     IWineD3DDeviceImpl_EndStateBlock,
6092     /*** Scene management ***/
6093     IWineD3DDeviceImpl_BeginScene,
6094     IWineD3DDeviceImpl_EndScene,
6095     IWineD3DDeviceImpl_Present,
6096     IWineD3DDeviceImpl_Clear,
6097     /*** Drawing ***/
6098     IWineD3DDeviceImpl_DrawPrimitive,
6099     IWineD3DDeviceImpl_DrawIndexedPrimitive,
6100     IWineD3DDeviceImpl_DrawPrimitiveUP,
6101     IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6102     IWineD3DDeviceImpl_DrawPrimitiveStrided,
6103     IWineD3DDeviceImpl_DrawRectPatch,
6104     IWineD3DDeviceImpl_DrawTriPatch,
6105     IWineD3DDeviceImpl_DeletePatch,
6106     IWineD3DDeviceImpl_ColorFill,
6107     IWineD3DDeviceImpl_UpdateTexture,
6108     IWineD3DDeviceImpl_UpdateSurface,
6109     IWineD3DDeviceImpl_GetFrontBufferData,
6110     /*** object tracking ***/
6111     IWineD3DDeviceImpl_ResourceReleased
6112 };
6113
6114
6115 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6116     WINED3DRS_ALPHABLENDENABLE   ,
6117     WINED3DRS_ALPHAFUNC          ,
6118     WINED3DRS_ALPHAREF           ,
6119     WINED3DRS_ALPHATESTENABLE    ,
6120     WINED3DRS_BLENDOP            ,
6121     WINED3DRS_COLORWRITEENABLE   ,
6122     WINED3DRS_DESTBLEND          ,
6123     WINED3DRS_DITHERENABLE       ,
6124     WINED3DRS_FILLMODE           ,
6125     WINED3DRS_FOGDENSITY         ,
6126     WINED3DRS_FOGEND             ,
6127     WINED3DRS_FOGSTART           ,
6128     WINED3DRS_LASTPIXEL          ,
6129     WINED3DRS_SHADEMODE          ,
6130     WINED3DRS_SRCBLEND           ,
6131     WINED3DRS_STENCILENABLE      ,
6132     WINED3DRS_STENCILFAIL        ,
6133     WINED3DRS_STENCILFUNC        ,
6134     WINED3DRS_STENCILMASK        ,
6135     WINED3DRS_STENCILPASS        ,
6136     WINED3DRS_STENCILREF         ,
6137     WINED3DRS_STENCILWRITEMASK   ,
6138     WINED3DRS_STENCILZFAIL       ,
6139     WINED3DRS_TEXTUREFACTOR      ,
6140     WINED3DRS_WRAP0              ,
6141     WINED3DRS_WRAP1              ,
6142     WINED3DRS_WRAP2              ,
6143     WINED3DRS_WRAP3              ,
6144     WINED3DRS_WRAP4              ,
6145     WINED3DRS_WRAP5              ,
6146     WINED3DRS_WRAP6              ,
6147     WINED3DRS_WRAP7              ,
6148     WINED3DRS_ZENABLE            ,
6149     WINED3DRS_ZFUNC              ,
6150     WINED3DRS_ZWRITEENABLE
6151 };
6152
6153 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6154     WINED3DTSS_ADDRESSW              ,
6155     WINED3DTSS_ALPHAARG0             ,
6156     WINED3DTSS_ALPHAARG1             ,
6157     WINED3DTSS_ALPHAARG2             ,
6158     WINED3DTSS_ALPHAOP               ,
6159     WINED3DTSS_BUMPENVLOFFSET        ,
6160     WINED3DTSS_BUMPENVLSCALE         ,
6161     WINED3DTSS_BUMPENVMAT00          ,
6162     WINED3DTSS_BUMPENVMAT01          ,
6163     WINED3DTSS_BUMPENVMAT10          ,
6164     WINED3DTSS_BUMPENVMAT11          ,
6165     WINED3DTSS_COLORARG0             ,
6166     WINED3DTSS_COLORARG1             ,
6167     WINED3DTSS_COLORARG2             ,
6168     WINED3DTSS_COLOROP               ,
6169     WINED3DTSS_RESULTARG             ,
6170     WINED3DTSS_TEXCOORDINDEX         ,
6171     WINED3DTSS_TEXTURETRANSFORMFLAGS
6172 };
6173
6174 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6175     WINED3DSAMP_ADDRESSU         ,
6176     WINED3DSAMP_ADDRESSV         ,
6177     WINED3DSAMP_ADDRESSW         ,
6178     WINED3DSAMP_BORDERCOLOR      ,
6179     WINED3DSAMP_MAGFILTER        ,
6180     WINED3DSAMP_MINFILTER        ,
6181     WINED3DSAMP_MIPFILTER        ,
6182     WINED3DSAMP_MIPMAPLODBIAS    ,
6183     WINED3DSAMP_MAXMIPLEVEL      ,
6184     WINED3DSAMP_MAXANISOTROPY    ,
6185     WINED3DSAMP_SRGBTEXTURE      ,
6186     WINED3DSAMP_ELEMENTINDEX
6187 };
6188
6189 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6190     WINED3DRS_AMBIENT                       ,
6191     WINED3DRS_AMBIENTMATERIALSOURCE         ,
6192     WINED3DRS_CLIPPING                      ,
6193     WINED3DRS_CLIPPLANEENABLE               ,
6194     WINED3DRS_COLORVERTEX                   ,
6195     WINED3DRS_DIFFUSEMATERIALSOURCE         ,
6196     WINED3DRS_EMISSIVEMATERIALSOURCE        ,
6197     WINED3DRS_FOGDENSITY                    ,
6198     WINED3DRS_FOGEND                        ,
6199     WINED3DRS_FOGSTART                      ,
6200     WINED3DRS_FOGTABLEMODE                  ,
6201     WINED3DRS_FOGVERTEXMODE                 ,
6202     WINED3DRS_INDEXEDVERTEXBLENDENABLE      ,
6203     WINED3DRS_LIGHTING                      ,
6204     WINED3DRS_LOCALVIEWER                   ,
6205     WINED3DRS_MULTISAMPLEANTIALIAS          ,
6206     WINED3DRS_MULTISAMPLEMASK               ,
6207     WINED3DRS_NORMALIZENORMALS              ,
6208     WINED3DRS_PATCHEDGESTYLE                ,
6209     WINED3DRS_POINTSCALE_A                  ,
6210     WINED3DRS_POINTSCALE_B                  ,
6211     WINED3DRS_POINTSCALE_C                  ,
6212     WINED3DRS_POINTSCALEENABLE              ,
6213     WINED3DRS_POINTSIZE                     ,
6214     WINED3DRS_POINTSIZE_MAX                 ,
6215     WINED3DRS_POINTSIZE_MIN                 ,
6216     WINED3DRS_POINTSPRITEENABLE             ,
6217     WINED3DRS_RANGEFOGENABLE                ,
6218     WINED3DRS_SPECULARMATERIALSOURCE        ,
6219     WINED3DRS_TWEENFACTOR                   ,
6220     WINED3DRS_VERTEXBLEND
6221 };
6222
6223 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6224     WINED3DTSS_TEXCOORDINDEX         ,
6225     WINED3DTSS_TEXTURETRANSFORMFLAGS
6226 };
6227
6228 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6229     WINED3DSAMP_DMAPOFFSET
6230 };
6231
6232 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
6233     DWORD rep = StateTable[state].representative;
6234     DWORD idx;
6235     BYTE shift;
6236     UINT i;
6237     WineD3DContext *context;
6238
6239     if(!rep) return;
6240     for(i = 0; i < This->numContexts; i++) {
6241         context = This->contexts[i];
6242         if(isStateDirty(context, rep)) continue;
6243
6244         context->dirtyArray[context->numDirtyEntries++] = rep;
6245         idx = rep >> 5;
6246         shift = rep & 0x1f;
6247         context->isStateDirty[idx] |= (1 << shift);
6248     }
6249 }