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