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