2 * IWineD3DDevice implementation
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
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.
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.
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
32 #include "wined3d_private.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
37 /* Define the default light parameters as specified by MSDN */
38 const WINED3DLIGHT WINED3D_default_light = {
40 WINED3DLIGHT_DIRECTIONAL, /* Type */
41 { 1.0, 1.0, 1.0, 0.0 }, /* Diffuse r,g,b,a */
42 { 0.0, 0.0, 0.0, 0.0 }, /* Specular r,g,b,a */
43 { 0.0, 0.0, 0.0, 0.0 }, /* Ambient r,g,b,a, */
44 { 0.0, 0.0, 0.0 }, /* Position x,y,z */
45 { 0.0, 0.0, 1.0 }, /* Direction x,y,z */
48 0.0, 0.0, 0.0, /* Attenuation 0,1,2 */
53 /* x11drv GDI escapes */
54 #define X11DRV_ESCAPE 6789
55 enum x11drv_escape_codes
57 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
58 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
59 X11DRV_GET_FONT, /* get current X font for a DC */
62 /* retrieve the X display to use on a given DC */
63 inline static Display *get_display( HDC hdc )
66 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
68 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
69 sizeof(display), (LPSTR)&display )) display = NULL;
73 /* allocate one pbuffer per surface */
74 BOOL pbuffer_per_surface = FALSE;
76 /* static function declarations */
77 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
79 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil);
82 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return WINED3DERR_OUTOFVIDEOMEMORY;}
84 #define D3DCREATEOBJECTINSTANCE(object, type) { \
85 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
86 D3DMEMCHECK(object, pp##type); \
87 object->lpVtbl = &IWineD3D##type##_Vtbl; \
88 object->wineD3DDevice = This; \
89 object->parent = parent; \
91 *pp##type = (IWineD3D##type *) object; \
94 #define D3DCREATESHADEROBJECTINSTANCE(object, type) { \
95 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
96 D3DMEMCHECK(object, pp##type); \
97 object->lpVtbl = &IWineD3D##type##_Vtbl; \
98 object->parent = parent; \
100 object->baseShader.device = (IWineD3DDevice*) This; \
101 list_init(&object->baseShader.linked_programs); \
102 *pp##type = (IWineD3D##type *) object; \
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); \
123 return WINED3DERR_OUTOFVIDEOMEMORY; \
125 globalChangeGlRam(_size); \
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); \
132 return WINED3DERR_OUTOFVIDEOMEMORY; \
134 *pp##type = (IWineD3D##type *) object; \
135 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
136 TRACE("(%p) : Created resource %p\n", This, object); \
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; \
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 */
151 /**********************************************************
152 * IUnknown parts follows
153 **********************************************************/
155 static HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
157 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
159 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
160 if (IsEqualGUID(riid, &IID_IUnknown)
161 || IsEqualGUID(riid, &IID_IWineD3DBase)
162 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
163 IUnknown_AddRef(iface);
168 return E_NOINTERFACE;
171 static ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
172 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
173 ULONG refCount = InterlockedIncrement(&This->ref);
175 TRACE("(%p) : AddRef increasing from %d\n", This, refCount - 1);
179 static ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
180 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
181 ULONG refCount = InterlockedDecrement(&This->ref);
183 TRACE("(%p) : Releasing from %d\n", This, refCount + 1);
187 GL_EXTCALL(glDeleteFramebuffersEXT(1, &This->fbo));
190 HeapFree(GetProcessHeap(), 0, This->render_targets);
192 HeapFree(GetProcessHeap(), 0, This->draw_buffers);
194 if (This->glsl_program_lookup) hash_table_destroy(This->glsl_program_lookup);
196 /* TODO: Clean up all the surfaces and textures! */
197 /* NOTE: You must release the parent if the object was created via a callback
198 ** ***************************/
200 /* Release the update stateblock */
201 if(IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->updateStateBlock) > 0){
202 if(This->updateStateBlock != This->stateBlock)
203 FIXME("(%p) Something's still holding the Update stateblock\n",This);
205 This->updateStateBlock = NULL;
206 { /* because were not doing proper internal refcounts releasing the primary state block
207 causes recursion with the extra checks in ResourceReleased, to avoid this we have
208 to set this->stateBlock = NULL; first */
209 IWineD3DStateBlock *stateBlock = (IWineD3DStateBlock *)This->stateBlock;
210 This->stateBlock = NULL;
212 /* Release the stateblock */
213 if(IWineD3DStateBlock_Release(stateBlock) > 0){
214 FIXME("(%p) Something's still holding the Update stateblock\n",This);
218 if (This->resources != NULL ) {
219 FIXME("(%p) Device released with resources still bound, acceptable but unexpected\n", This);
220 dumpResources(This->resources);
223 if(This->contexts) ERR("Context array not freed!\n");
225 IWineD3D_Release(This->wineD3D);
226 This->wineD3D = NULL;
227 HeapFree(GetProcessHeap(), 0, This);
228 TRACE("Freed device %p\n", This);
234 /**********************************************************
235 * IWineD3DDevice implementation follows
236 **********************************************************/
237 static HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
238 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
239 *pParent = This->parent;
240 IUnknown_AddRef(This->parent);
244 static void CreateVBO(IWineD3DVertexBufferImpl *object) {
245 IWineD3DDeviceImpl *This = object->resource.wineD3DDevice; /* Needed for GL_EXTCALL */
246 GLenum error, glUsage;
247 DWORD vboUsage = object->resource.usage;
248 if(object->Flags & VBFLAG_VBOCREATEFAIL) {
249 WARN("Creating a vbo failed once, not trying again\n");
253 TRACE("Creating an OpenGL vertex buffer object for IWineD3DVertexBuffer %p Usage(%s)\n", object, debug_d3dusage(vboUsage));
256 /* Make sure that the gl error is cleared. Do not use checkGLcall
257 * here because checkGLcall just prints a fixme and continues. However,
258 * if an error during VBO creation occurs we can fall back to non-vbo operation
259 * with full functionality(but performance loss)
261 while(glGetError() != GL_NO_ERROR);
263 /* Basically the FVF parameter passed to CreateVertexBuffer is no good
264 * It is the FVF set with IWineD3DDevice::SetFVF or the Vertex Declaration set with
265 * IWineD3DDevice::SetVertexDeclaration that decides how the vertices in the buffer
266 * look like. This means that on each DrawPrimitive call the vertex buffer has to be verified
267 * to check if the rhw and color values are in the correct format.
270 GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
271 error = glGetError();
272 if(object->vbo == 0 || error != GL_NO_ERROR) {
273 WARN("Failed to create a VBO with error %d\n", error);
277 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, object->vbo));
278 error = glGetError();
279 if(error != GL_NO_ERROR) {
280 WARN("Failed to bind the VBO, error %d\n", error);
284 /* Don't use static, because dx apps tend to update the buffer
285 * quite often even if they specify 0 usage. Because we always keep the local copy
286 * we never read from the vbo and can create a write only opengl buffer.
288 switch(vboUsage & (WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC) ) {
289 case WINED3DUSAGE_WRITEONLY | WINED3DUSAGE_DYNAMIC:
290 case WINED3DUSAGE_DYNAMIC:
291 TRACE("Gl usage = GL_STREAM_DRAW\n");
292 glUsage = GL_STREAM_DRAW_ARB;
294 case WINED3DUSAGE_WRITEONLY:
296 TRACE("Gl usage = GL_DYNAMIC_DRAW\n");
297 glUsage = GL_DYNAMIC_DRAW_ARB;
301 /* Reserve memory for the buffer. The amount of data won't change
302 * so we are safe with calling glBufferData once with a NULL ptr and
303 * calling glBufferSubData on updates
305 GL_EXTCALL(glBufferDataARB(GL_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
306 error = glGetError();
307 if(error != GL_NO_ERROR) {
308 WARN("glBufferDataARB failed with error %d\n", error);
316 /* Clean up all vbo init, but continue because we can work without a vbo :-) */
317 FIXME("Failed to create a vertex buffer object. Continuing, but performance issues can occur\n");
318 if(object->vbo) GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
320 object->Flags |= VBFLAG_VBOCREATEFAIL;
325 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
326 DWORD FVF, WINED3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
328 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
329 IWineD3DVertexBufferImpl *object;
330 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
331 int dxVersion = ( (IWineD3DImpl *) This->wineD3D)->dxVersion;
335 WARN("Size 0 requested, returning WINED3DERR_INVALIDCALL\n");
336 *ppVertexBuffer = NULL;
337 return WINED3DERR_INVALIDCALL;
340 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, WINED3DRTYPE_VERTEXBUFFER, Size)
342 TRACE("(%p) : Size=%d, Usage=%d, FVF=%x, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
343 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
345 if (Pool == WINED3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
346 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
350 /* Observations show that drawStridedSlow is faster on dynamic VBs than converting +
351 * drawStridedFast (half-life 2).
353 * Basically converting the vertices in the buffer is quite expensive, and observations
354 * show that drawStridedSlow is faster than converting + uploading + drawStridedFast.
355 * Therefore do not create a VBO for WINED3DUSAGE_DYNAMIC buffers.
357 * Direct3D7 has another problem: Its vertexbuffer api doesn't offer a way to specify
358 * the range of vertices being locked, so each lock will require the whole buffer to be transformed.
359 * Moreover geometry data in dx7 is quite simple, so drawStridedSlow isn't a big hit. A plus
360 * is that the vertex buffers fvf can be trusted in dx7. So only create non-converted vbos for
362 * There is a IDirect3DVertexBuffer7::Optimize call after which the buffer can't be locked any
363 * more. In this call we can convert dx7 buffers too.
365 conv = ((FVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) || (FVF & (WINED3DFVF_DIFFUSE | WINED3DFVF_SPECULAR));
366 if( GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) && Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) &&
367 (dxVersion > 7 || !conv) ) {
373 static void CreateIndexBufferVBO(IWineD3DDeviceImpl *This, IWineD3DIndexBufferImpl *object) {
374 GLenum error, glUsage;
375 TRACE("Creating VBO for Index Buffer %p\n", object);
377 /* The following code will modify the ELEMENT_ARRAY_BUFFER binding, make sure it is
378 * restored on the next draw
380 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
385 GL_EXTCALL(glGenBuffersARB(1, &object->vbo));
386 error = glGetError();
387 if(error != GL_NO_ERROR || object->vbo == 0) {
388 ERR("Creating a vbo failed, continueing without vbo for this buffer\n");
392 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->vbo));
393 error = glGetError();
394 if(error != GL_NO_ERROR) {
395 ERR("Failed to bind index buffer, continueing without vbo for this buffer\n");
399 /* Use static write only usage for now. Dynamic index buffers stay in sysmem, and due to the sysmem
400 * copy no readback will be needed
402 glUsage = GL_STATIC_DRAW_ARB;
403 GL_EXTCALL(glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, object->resource.size, NULL, glUsage));
404 error = glGetError();
405 if(error != GL_NO_ERROR) {
406 ERR("Failed to initialize the index buffer\n");
410 TRACE("Successfully created vbo %d for index buffer %p\n", object->vbo, object);
414 GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
415 GL_EXTCALL(glDeleteBuffersARB(1, &object->vbo));
420 static HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
421 WINED3DFORMAT Format, WINED3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
422 HANDLE *sharedHandle, IUnknown *parent) {
423 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
424 IWineD3DIndexBufferImpl *object;
425 TRACE("(%p) Creating index buffer\n", This);
427 /* Allocate the storage for the device */
428 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,WINED3DRTYPE_INDEXBUFFER, Length)
430 if (Pool == WINED3DPOOL_DEFAULT ) { /* We need a local copy for drawStridedSlow */
431 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
434 if(Pool != WINED3DPOOL_SYSTEMMEM && !(Usage & WINED3DUSAGE_DYNAMIC) && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
435 CreateIndexBufferVBO(This, object);
438 TRACE("(%p) : Len=%d, Use=%x, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
439 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
440 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
445 static HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
447 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
448 IWineD3DStateBlockImpl *object;
452 D3DCREATEOBJECTINSTANCE(object, StateBlock)
453 object->blockType = Type;
455 for(i = 0; i < LIGHTMAP_SIZE; i++) {
456 list_init(&object->lightMap[i]);
459 /* Special case - Used during initialization to produce a placeholder stateblock
460 so other functions called can update a state block */
461 if (Type == WINED3DSBT_INIT) {
462 /* Don't bother increasing the reference count otherwise a device will never
463 be freed due to circular dependencies */
467 temp_result = allocate_shader_constants(object);
468 if (WINED3D_OK != temp_result)
471 /* Otherwise, might as well set the whole state block to the appropriate values */
472 if (This->stateBlock != NULL)
473 stateblock_copy((IWineD3DStateBlock*) object, (IWineD3DStateBlock*) This->stateBlock);
475 memset(object->streamFreq, 1, sizeof(object->streamFreq));
477 /* Reset the ref and type after kludging it */
478 object->wineD3DDevice = This;
480 object->blockType = Type;
482 TRACE("Updating changed flags appropriate for type %d\n", Type);
484 if (Type == WINED3DSBT_ALL) {
486 TRACE("ALL => Pretend everything has changed\n");
487 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, TRUE);
489 /* Lights are not part of the changed / set structure */
490 for(j = 0; j < LIGHTMAP_SIZE; j++) {
492 LIST_FOR_EACH(e, &object->lightMap[j]) {
493 PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
494 light->changed = TRUE;
495 light->enabledChanged = TRUE;
498 } else if (Type == WINED3DSBT_PIXELSTATE) {
500 TRACE("PIXELSTATE => Pretend all pixel shates have changed\n");
501 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
503 object->changed.pixelShader = TRUE;
505 /* Pixel Shader Constants */
506 for (i = 0; i < GL_LIMITS(pshader_constantsF); ++i)
507 object->changed.pixelShaderConstantsF[i] = TRUE;
508 for (i = 0; i < MAX_CONST_B; ++i)
509 object->changed.pixelShaderConstantsB[i] = TRUE;
510 for (i = 0; i < MAX_CONST_I; ++i)
511 object->changed.pixelShaderConstantsI[i] = TRUE;
513 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
514 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
516 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
517 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
518 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
521 for (j = 0 ; j < 16; j++) {
522 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
524 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
528 } else if (Type == WINED3DSBT_VERTEXSTATE) {
530 TRACE("VERTEXSTATE => Pretend all vertex shates have changed\n");
531 stateblock_savedstates_set((IWineD3DStateBlock*) object, &object->changed, FALSE);
533 object->changed.vertexShader = TRUE;
535 /* Vertex Shader Constants */
536 for (i = 0; i < GL_LIMITS(vshader_constantsF); ++i)
537 object->changed.vertexShaderConstantsF[i] = TRUE;
538 for (i = 0; i < MAX_CONST_B; ++i)
539 object->changed.vertexShaderConstantsB[i] = TRUE;
540 for (i = 0; i < MAX_CONST_I; ++i)
541 object->changed.vertexShaderConstantsI[i] = TRUE;
543 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
544 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
546 for (j = 0; j < GL_LIMITS(texture_stages); j++) {
547 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
548 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
551 for (j = 0 ; j < 16; j++){
552 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
553 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
557 for(j = 0; j < LIGHTMAP_SIZE; j++) {
559 LIST_FOR_EACH(e, &object->lightMap[j]) {
560 PLIGHTINFOEL *light = LIST_ENTRY(e, PLIGHTINFOEL, entry);
561 light->changed = TRUE;
562 light->enabledChanged = TRUE;
566 FIXME("Unrecognized state block type %d\n", Type);
569 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
574 /* ************************************
576 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
579 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
581 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.
583 ******************************** */
585 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) {
586 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
587 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
588 unsigned int pow2Width, pow2Height;
589 unsigned int Size = 1;
590 const PixelFormatDesc *tableEntry = getFormatDescEntry(Format);
591 TRACE("(%p) Create surface\n",This);
593 /** FIXME: Check ranges on the inputs are valid
596 * [in] Quality level. The valid range is between zero and one less than the level
597 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
598 * Passing a larger value returns the error WINED3DERR_INVALIDCALL. The MultisampleQuality
599 * values of paired render targets, depth stencil surfaces, and the MultiSample type
601 *******************************/
606 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
608 * If this flag is set, the contents of the depth stencil buffer will be
609 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
610 * with a different depth surface.
612 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
613 ***************************/
615 if(MultisampleQuality < 0) {
616 FIXME("Invalid multisample level %d\n", MultisampleQuality);
617 return WINED3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
620 if(MultisampleQuality > 0) {
621 FIXME("MultisampleQuality set to %d, substituting 0\n", MultisampleQuality);
622 MultisampleQuality=0;
625 /** FIXME: Check that the format is supported
627 *******************************/
629 /* Non-power2 support */
630 if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
634 /* Find the nearest pow2 match */
635 pow2Width = pow2Height = 1;
636 while (pow2Width < Width) pow2Width <<= 1;
637 while (pow2Height < Height) pow2Height <<= 1;
640 if (pow2Width > Width || pow2Height > Height) {
641 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
642 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
643 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
644 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d)\n",
645 This, Width, Height);
646 return WINED3DERR_NOTAVAILABLE;
650 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
651 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
653 *********************************/
654 if (WINED3DFMT_UNKNOWN == Format) {
656 } else if (Format == WINED3DFMT_DXT1) {
657 /* DXT1 is half byte per pixel */
658 Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4)) >> 1;
660 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
661 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
662 Size = ((max(Width,4) * tableEntry->bpp) * max(Height,4));
664 /* The pitch is a multiple of 4 bytes */
665 Size = ((Width * tableEntry->bpp) + SURFACE_ALIGNMENT - 1) & ~(SURFACE_ALIGNMENT - 1);
669 /** Create and initialise the surface resource **/
670 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,WINED3DRTYPE_SURFACE, Size)
671 /* "Standalone" surface */
672 IWineD3DSurface_SetContainer((IWineD3DSurface *)object, NULL);
674 object->currentDesc.Width = Width;
675 object->currentDesc.Height = Height;
676 object->currentDesc.MultiSampleType = MultiSample;
677 object->currentDesc.MultiSampleQuality = MultisampleQuality;
679 /* Setup some glformat defaults */
680 object->glDescription.glFormat = tableEntry->glFormat;
681 object->glDescription.glFormatInternal = tableEntry->glInternal;
682 object->glDescription.glType = tableEntry->glType;
684 object->glDescription.textureName = 0;
685 object->glDescription.level = Level;
686 object->glDescription.target = GL_TEXTURE_2D;
689 object->pow2Width = pow2Width;
690 object->pow2Height = pow2Height;
693 object->Flags = 0; /* We start without flags set */
694 object->Flags |= (pow2Width != Width || pow2Height != Height) ? SFLAG_NONPOW2 : 0;
695 object->Flags |= Discard ? SFLAG_DISCARD : 0;
696 object->Flags |= (WINED3DFMT_D16_LOCKABLE == Format) ? SFLAG_LOCKABLE : 0;
697 object->Flags |= Lockable ? SFLAG_LOCKABLE : 0;
700 if (WINED3DFMT_UNKNOWN != Format) {
701 object->bytesPerPixel = tableEntry->bpp;
703 object->bytesPerPixel = 0;
706 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
708 TRACE("Pool %d %d %d %d\n",Pool, WINED3DPOOL_DEFAULT, WINED3DPOOL_MANAGED, WINED3DPOOL_SYSTEMMEM);
710 /** Quick lockable sanity check TODO: remove this after surfaces, usage and lockability have been debugged properly
711 * this function is too deep to need to care about things like this.
712 * Levels need to be checked too, and possibly Type since they all affect what can be done.
713 * ****************************************/
715 case WINED3DPOOL_SCRATCH:
717 FIXME("Create surface called with a pool of SCRATCH and a Lockable of FALSE "
718 "which are mutually exclusive, setting lockable to TRUE\n");
721 case WINED3DPOOL_SYSTEMMEM:
722 if(!Lockable) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, "
723 "this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
724 case WINED3DPOOL_MANAGED:
725 if(Usage == WINED3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a "
726 "Usage of DYNAMIC which are mutually exclusive, not doing "
727 "anything just telling you.\n");
729 case WINED3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
730 if(!(Usage & WINED3DUSAGE_DYNAMIC) && !(Usage & WINED3DUSAGE_RENDERTARGET)
731 && !(Usage && WINED3DUSAGE_DEPTHSTENCIL ) && Lockable)
732 WARN("Creating a surface with a POOL of DEFAULT with Lockable true, that doesn't specify DYNAMIC usage.\n");
735 FIXME("(%p) Unknown pool %d\n", This, Pool);
739 if (Usage & WINED3DUSAGE_RENDERTARGET && Pool != WINED3DPOOL_DEFAULT) {
740 FIXME("Trying to create a render target that isn't in the default pool\n");
743 /* mark the texture as dirty so that it gets loaded first time around*/
744 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
745 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
746 This, Width, Height, Format, debug_d3dformat(Format),
747 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
749 /* Store the DirectDraw primary surface. This is the first rendertarget surface created */
750 if( (Usage & WINED3DUSAGE_RENDERTARGET) && (!This->ddraw_primary) )
751 This->ddraw_primary = (IWineD3DSurface *) object;
753 /* Look at the implementation and set the correct Vtable */
756 /* Nothing to do, it's set already */
760 object->lpVtbl = &IWineGDISurface_Vtbl;
764 /* To be sure to catch this */
765 ERR("Unknown requested surface implementation %d!\n", Impl);
766 IWineD3DSurface_Release((IWineD3DSurface *) object);
767 return WINED3DERR_INVALIDCALL;
770 /* Call the private setup routine */
771 return IWineD3DSurface_PrivateSetup( (IWineD3DSurface *) object );
775 static HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
776 DWORD Usage, WINED3DFORMAT Format, WINED3DPOOL Pool,
777 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
778 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
780 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
781 IWineD3DTextureImpl *object;
786 unsigned int pow2Width;
787 unsigned int pow2Height;
790 TRACE("(%p) : Width %d, Height %d, Levels %d, Usage %#x\n", This, Width, Height, Levels, Usage);
791 TRACE("Format %#x (%s), Pool %#x, ppTexture %p, pSharedHandle %p, parent %p\n",
792 Format, debug_d3dformat(Format), Pool, ppTexture, pSharedHandle, parent);
794 /* TODO: It should only be possible to create textures for formats
795 that are reported as supported */
796 if (WINED3DFMT_UNKNOWN >= Format) {
797 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
798 return WINED3DERR_INVALIDCALL;
801 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, WINED3DRTYPE_TEXTURE, 0);
802 D3DINITIALIZEBASETEXTURE(object->baseTexture);
803 object->width = Width;
804 object->height = Height;
806 /** Non-power2 support **/
807 if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
811 /* Find the nearest pow2 match */
812 pow2Width = pow2Height = 1;
813 while (pow2Width < Width) pow2Width <<= 1;
814 while (pow2Height < Height) pow2Height <<= 1;
817 /** FIXME: add support for real non-power-two if it's provided by the video card **/
818 /* Precalculated scaling for 'faked' non power of two texture coords */
819 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
820 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
821 TRACE(" xf(%f) yf(%f)\n", object->pow2scalingFactorX, object->pow2scalingFactorY);
823 /* Calculate levels for mip mapping */
825 TRACE("calculating levels %d\n", object->baseTexture.levels);
826 object->baseTexture.levels++;
829 while (tmpW > 1 || tmpH > 1) {
830 tmpW = max(1, tmpW >> 1);
831 tmpH = max(1, tmpH >> 1);
832 object->baseTexture.levels++;
834 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
837 /* Generate all the surfaces */
840 for (i = 0; i < object->baseTexture.levels; i++)
842 /* use the callback to create the texture surface */
843 hr = D3DCB_CreateSurface(This->parent, parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
844 if (hr!= WINED3D_OK || ( (IWineD3DSurfaceImpl *) object->surfaces[i])->Flags & SFLAG_OVERSIZE) {
845 FIXME("Failed to create surface %p\n", object);
847 object->surfaces[i] = NULL;
848 IWineD3DTexture_Release((IWineD3DTexture *)object);
854 IWineD3DSurface_SetContainer(object->surfaces[i], (IWineD3DBase *)object);
855 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
856 /* calculate the next mipmap level */
857 tmpW = max(1, tmpW >> 1);
858 tmpH = max(1, tmpH >> 1);
861 TRACE("(%p) : Created texture %p\n", This, object);
865 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
866 UINT Width, UINT Height, UINT Depth,
867 UINT Levels, DWORD Usage,
868 WINED3DFORMAT Format, WINED3DPOOL Pool,
869 IWineD3DVolumeTexture **ppVolumeTexture,
870 HANDLE *pSharedHandle, IUnknown *parent,
871 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
873 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
874 IWineD3DVolumeTextureImpl *object;
880 /* TODO: It should only be possible to create textures for formats
881 that are reported as supported */
882 if (WINED3DFMT_UNKNOWN >= Format) {
883 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
884 return WINED3DERR_INVALIDCALL;
887 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, WINED3DRTYPE_VOLUMETEXTURE, 0);
888 D3DINITIALIZEBASETEXTURE(object->baseTexture);
890 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
891 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
893 object->width = Width;
894 object->height = Height;
895 object->depth = Depth;
897 /* Calculate levels for mip mapping */
899 object->baseTexture.levels++;
903 while (tmpW > 1 || tmpH > 1 || tmpD > 1) {
904 tmpW = max(1, tmpW >> 1);
905 tmpH = max(1, tmpH >> 1);
906 tmpD = max(1, tmpD >> 1);
907 object->baseTexture.levels++;
909 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
912 /* Generate all the surfaces */
917 for (i = 0; i < object->baseTexture.levels; i++)
920 /* Create the volume */
921 hr = D3DCB_CreateVolume(This->parent, parent, Width, Height, Depth, Format, Pool, Usage,
922 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
925 ERR("Creating a volume for the volume texture failed(%08x)\n", hr);
926 IWineD3DVolumeTexture_Release((IWineD3DVolumeTexture *) object);
927 *ppVolumeTexture = NULL;
931 /* Set its container to this object */
932 IWineD3DVolume_SetContainer(object->volumes[i], (IWineD3DBase *)object);
934 /* calcualte the next mipmap level */
935 tmpW = max(1, tmpW >> 1);
936 tmpH = max(1, tmpH >> 1);
937 tmpD = max(1, tmpD >> 1);
940 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
941 TRACE("(%p) : Created volume texture %p\n", This, object);
945 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
946 UINT Width, UINT Height, UINT Depth,
948 WINED3DFORMAT Format, WINED3DPOOL Pool,
949 IWineD3DVolume** ppVolume,
950 HANDLE* pSharedHandle, IUnknown *parent) {
952 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
953 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
954 const PixelFormatDesc *formatDesc = getFormatDescEntry(Format);
956 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, WINED3DRTYPE_VOLUME, ((Width * formatDesc->bpp) * Height * Depth))
958 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
959 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
961 object->currentDesc.Width = Width;
962 object->currentDesc.Height = Height;
963 object->currentDesc.Depth = Depth;
964 object->bytesPerPixel = formatDesc->bpp;
966 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
967 object->lockable = TRUE;
968 object->locked = FALSE;
969 memset(&object->lockedBox, 0, sizeof(WINED3DBOX));
970 object->dirty = TRUE;
972 return IWineD3DVolume_AddDirtyBox((IWineD3DVolume *) object, NULL);
975 static HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
976 UINT Levels, DWORD Usage,
977 WINED3DFORMAT Format, WINED3DPOOL Pool,
978 IWineD3DCubeTexture **ppCubeTexture,
979 HANDLE *pSharedHandle, IUnknown *parent,
980 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
982 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
983 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
987 unsigned int pow2EdgeLength = EdgeLength;
989 /* TODO: It should only be possible to create textures for formats
990 that are reported as supported */
991 if (WINED3DFMT_UNKNOWN >= Format) {
992 WARN("(%p) : Texture cannot be created with a format of WINED3DFMT_UNKNOWN\n", This);
993 return WINED3DERR_INVALIDCALL;
996 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, WINED3DRTYPE_CUBETEXTURE, 0);
997 D3DINITIALIZEBASETEXTURE(object->baseTexture);
999 TRACE("(%p) Create Cube Texture\n", This);
1001 /** Non-power2 support **/
1003 /* Find the nearest pow2 match */
1005 while (pow2EdgeLength < EdgeLength) pow2EdgeLength <<= 1;
1007 object->edgeLength = EdgeLength;
1008 /* TODO: support for native non-power 2 */
1009 /* Precalculated scaling for 'faked' non power of two texture coords */
1010 object->pow2scalingFactor = ((float)EdgeLength) / ((float)pow2EdgeLength);
1012 /* Calculate levels for mip mapping */
1014 object->baseTexture.levels++;
1017 tmpW = max(1, tmpW >> 1);
1018 object->baseTexture.levels++;
1020 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
1023 /* Generate all the surfaces */
1025 for (i = 0; i < object->baseTexture.levels; i++) {
1027 /* Create the 6 faces */
1028 for (j = 0; j < 6; j++) {
1030 hr=D3DCB_CreateSurface(This->parent, parent, tmpW, tmpW, Format, Usage, Pool,
1031 i /* Level */, &object->surfaces[j][i],pSharedHandle);
1033 if(hr!= WINED3D_OK) {
1037 for (l = 0; l < j; l++) {
1038 IWineD3DSurface_Release(object->surfaces[j][i]);
1040 for (k = 0; k < i; k++) {
1041 for (l = 0; l < 6; l++) {
1042 IWineD3DSurface_Release(object->surfaces[l][j]);
1046 FIXME("(%p) Failed to create surface\n",object);
1047 HeapFree(GetProcessHeap(),0,object);
1048 *ppCubeTexture = NULL;
1051 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IWineD3DBase *)object);
1052 TRACE("Created surface level %d @ %p,\n", i, object->surfaces[j][i]);
1054 tmpW = max(1, tmpW >> 1);
1057 TRACE("(%p) : Created Cube Texture %p\n", This, object);
1058 *ppCubeTexture = (IWineD3DCubeTexture *) object;
1062 static HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
1063 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1064 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
1065 HRESULT hr = WINED3DERR_NOTAVAILABLE;
1067 /* Just a check to see if we support this type of query */
1069 case WINED3DQUERYTYPE_OCCLUSION:
1070 TRACE("(%p) occlusion query\n", This);
1071 if (GL_SUPPORT(ARB_OCCLUSION_QUERY))
1074 WARN("Unsupported in local OpenGL implementation: ARB_OCCLUSION_QUERY/NV_OCCLUSION_QUERY\n");
1077 case WINED3DQUERYTYPE_EVENT:
1078 if(!(GL_SUPPORT(NV_FENCE) || GL_SUPPORT(APPLE_FENCE) )) {
1079 /* Half-Life 2 needs this query. It does not render the main menu correctly otherwise
1080 * Pretend to support it, faking this query does not do much harm except potentially lowering performance
1082 FIXME("(%p) Event query: Unimplemented, but pretending to be supported\n", This);
1087 case WINED3DQUERYTYPE_VCACHE:
1088 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1089 case WINED3DQUERYTYPE_VERTEXSTATS:
1090 case WINED3DQUERYTYPE_TIMESTAMP:
1091 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1092 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1093 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1094 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1095 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1096 case WINED3DQUERYTYPE_PIXELTIMINGS:
1097 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1098 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1100 FIXME("(%p) Unhandled query type %d\n", This, Type);
1102 if(NULL == ppQuery || hr != WINED3D_OK) {
1106 D3DCREATEOBJECTINSTANCE(object, Query)
1107 object->type = Type;
1108 /* allocated the 'extended' data based on the type of query requested */
1110 case WINED3DQUERYTYPE_OCCLUSION:
1111 if(GL_SUPPORT(ARB_OCCLUSION_QUERY)) {
1112 TRACE("(%p) Allocating data for an occlusion query\n", This);
1113 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryOcclusionData));
1114 GL_EXTCALL(glGenQueriesARB(1, &((WineQueryOcclusionData *)(object->extendedData))->queryId));
1117 case WINED3DQUERYTYPE_EVENT:
1118 /* TODO: GL_APPLE_fence */
1119 if(GL_SUPPORT(APPLE_FENCE)) {
1120 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryEventData));
1121 GL_EXTCALL(glGenFencesAPPLE(1, &((WineQueryEventData *)(object->extendedData))->fenceId));
1122 checkGLcall("glGenFencesAPPLE");
1123 } else if(GL_SUPPORT(NV_FENCE)) {
1124 object->extendedData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(WineQueryEventData));
1125 GL_EXTCALL(glGenFencesNV(1, &((WineQueryEventData *)(object->extendedData))->fenceId));
1126 checkGLcall("glGenFencesNV");
1130 case WINED3DQUERYTYPE_VCACHE:
1131 case WINED3DQUERYTYPE_RESOURCEMANAGER:
1132 case WINED3DQUERYTYPE_VERTEXSTATS:
1133 case WINED3DQUERYTYPE_TIMESTAMP:
1134 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
1135 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
1136 case WINED3DQUERYTYPE_PIPELINETIMINGS:
1137 case WINED3DQUERYTYPE_INTERFACETIMINGS:
1138 case WINED3DQUERYTYPE_VERTEXTIMINGS:
1139 case WINED3DQUERYTYPE_PIXELTIMINGS:
1140 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
1141 case WINED3DQUERYTYPE_CACHEUTILIZATION:
1143 object->extendedData = 0;
1144 FIXME("(%p) Unhandled query type %d\n",This , Type);
1146 TRACE("(%p) : Created Query %p\n", This, object);
1150 /*****************************************************************************
1151 * IWineD3DDeviceImpl_SetupFullscreenWindow
1153 * Helper function that modifies a HWND's Style and ExStyle for proper
1157 * iface: Pointer to the IWineD3DDevice interface
1158 * window: Window to setup
1160 *****************************************************************************/
1161 static void WINAPI IWineD3DDeviceImpl_SetupFullscreenWindow(IWineD3DDevice *iface, HWND window) {
1162 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1164 LONG style, exStyle;
1165 /* Don't do anything if an original style is stored.
1166 * That shouldn't happen
1168 TRACE("(%p): Setting up window %p for exclusive mode\n", This, window);
1169 if (This->style || This->exStyle) {
1170 ERR("(%p): Want to change the window parameters of HWND %p, but "
1171 "another style is stored for restoration afterwards\n", This, window);
1174 /* Get the parameters and save them */
1175 style = GetWindowLongW(window, GWL_STYLE);
1176 exStyle = GetWindowLongW(window, GWL_EXSTYLE);
1177 This->style = style;
1178 This->exStyle = exStyle;
1180 /* Filter out window decorations */
1181 style &= ~WS_CAPTION;
1182 style &= ~WS_THICKFRAME;
1183 exStyle &= ~WS_EX_WINDOWEDGE;
1184 exStyle &= ~WS_EX_CLIENTEDGE;
1186 /* Make sure the window is managed, otherwise we won't get keyboard input */
1187 style |= WS_POPUP | WS_SYSMENU;
1189 TRACE("Old style was %08x,%08x, setting to %08x,%08x\n",
1190 This->style, This->exStyle, style, exStyle);
1192 SetWindowLongW(window, GWL_STYLE, style);
1193 SetWindowLongW(window, GWL_EXSTYLE, exStyle);
1195 /* Inform the window about the update. */
1196 SetWindowPos(window, HWND_TOP, 0, 0,
1197 This->ddraw_width, This->ddraw_height, SWP_FRAMECHANGED);
1198 ShowWindow(window, SW_NORMAL);
1201 /*****************************************************************************
1202 * IWineD3DDeviceImpl_RestoreWindow
1204 * Helper function that restores a windows' properties when taking it out
1205 * of fullscreen mode
1208 * iface: Pointer to the IWineD3DDevice interface
1209 * window: Window to setup
1211 *****************************************************************************/
1212 static void WINAPI IWineD3DDeviceImpl_RestoreWindow(IWineD3DDevice *iface, HWND window) {
1213 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1215 /* This could be a DDSCL_NORMAL -> DDSCL_NORMAL
1216 * switch, do nothing
1218 if (!This->style && !This->exStyle) return;
1220 TRACE("(%p): Restoring window settings of window %p to %08x, %08x\n",
1221 This, window, This->style, This->exStyle);
1223 SetWindowLongW(window, GWL_STYLE, This->style);
1224 SetWindowLongW(window, GWL_EXSTYLE, This->exStyle);
1226 /* Delete the old values */
1230 /* Inform the window about the update */
1231 SetWindowPos(window, 0 /* InsertAfter, ignored */,
1232 0, 0, 0, 0, /* Pos, Size, ignored */
1233 SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER);
1236 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
1237 static HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
1239 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
1240 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
1241 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1244 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1245 HRESULT hr = WINED3D_OK;
1246 IUnknown *bufferParent;
1249 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1251 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1252 * does a device hold a reference to a swap chain giving them a lifetime of the device
1253 * or does the swap chain notify the device of its destruction.
1254 *******************************/
1256 /* Check the params */
1257 if(pPresentationParameters->BackBufferCount > WINED3DPRESENT_BACK_BUFFER_MAX) {
1258 ERR("App requested %d back buffers, this is not supported for now\n", pPresentationParameters->BackBufferCount);
1259 return WINED3DERR_INVALIDCALL;
1260 } else if (pPresentationParameters->BackBufferCount > 1) {
1261 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");
1264 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1266 /*********************
1267 * Lookup the window Handle and the relating X window handle
1268 ********************/
1270 /* Setup hwnd we are using, plus which display this equates to */
1271 object->win_handle = pPresentationParameters->hDeviceWindow;
1272 if (!object->win_handle) {
1273 object->win_handle = This->createParms.hFocusWindow;
1276 object->win_handle = GetAncestor(object->win_handle, GA_ROOT);
1277 if ( !( object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window") ) ) {
1278 ERR("Can't get drawable (window), HWND:%p doesn't have the property __wine_x11_whole_window\n", object->win_handle);
1279 return WINED3DERR_NOTAVAILABLE;
1281 hDc = GetDC(object->win_handle);
1282 display = get_display(hDc);
1283 ReleaseDC(object->win_handle, hDc);
1284 TRACE("Using a display of %p %p\n", display, hDc);
1286 if (NULL == display || NULL == hDc) {
1287 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1288 return WINED3DERR_NOTAVAILABLE;
1291 if (object->win == 0) {
1292 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1293 return WINED3DERR_NOTAVAILABLE;
1296 object->orig_width = GetSystemMetrics(SM_CXSCREEN);
1297 object->orig_height = GetSystemMetrics(SM_CYSCREEN);
1298 object->orig_fmt = pixelformat_for_depth(GetDeviceCaps(hDc, BITSPIXEL) * GetDeviceCaps(hDc, PLANES));
1300 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1301 * then the corresponding dimension of the client area of the hDeviceWindow
1302 * (or the focus window, if hDeviceWindow is NULL) is taken.
1303 **********************/
1305 if (pPresentationParameters->Windowed &&
1306 ((pPresentationParameters->BackBufferWidth == 0) ||
1307 (pPresentationParameters->BackBufferHeight == 0))) {
1310 GetClientRect(object->win_handle, &Rect);
1312 if (pPresentationParameters->BackBufferWidth == 0) {
1313 pPresentationParameters->BackBufferWidth = Rect.right;
1314 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
1316 if (pPresentationParameters->BackBufferHeight == 0) {
1317 pPresentationParameters->BackBufferHeight = Rect.bottom;
1318 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
1322 /* Put the correct figures in the presentation parameters */
1323 TRACE("Copying across presentation parameters\n");
1324 object->presentParms = *pPresentationParameters;
1326 TRACE("calling rendertarget CB\n");
1327 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1329 object->presentParms.BackBufferWidth,
1330 object->presentParms.BackBufferHeight,
1331 object->presentParms.BackBufferFormat,
1332 object->presentParms.MultiSampleType,
1333 object->presentParms.MultiSampleQuality,
1334 TRUE /* Lockable */,
1335 &object->frontBuffer,
1336 NULL /* pShared (always null)*/);
1337 if (object->frontBuffer != NULL) {
1338 IWineD3DSurface_SetContainer(object->frontBuffer, (IWineD3DBase *)object);
1340 ERR("Failed to create the front buffer\n");
1345 * Create an opengl context for the display visual
1346 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1347 * use different properties after that point in time. FIXME: How to handle when requested format
1348 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1349 * it chooses is identical to the one already being used!
1350 **********************************/
1352 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1354 object->context = CreateContext(This, (IWineD3DSurfaceImpl *) object->frontBuffer, display, object->win);
1357 if (!object->context) {
1358 ERR("Failed to create a new context\n");
1359 hr = WINED3DERR_NOTAVAILABLE;
1362 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld)\n",
1363 object->win_handle, object->context->glCtx, object->win);
1366 /*********************
1367 * Windowed / Fullscreen
1368 *******************/
1371 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1372 * so we should really check to see if there is a fullscreen swapchain already
1373 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1374 **************************************/
1376 if (!pPresentationParameters->Windowed) {
1383 /* Get info on the current display setup */
1385 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1388 /* Change the display settings */
1389 memset(&devmode, 0, sizeof(DEVMODEW));
1390 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1391 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1392 devmode.dmPelsWidth = pPresentationParameters->BackBufferWidth;
1393 devmode.dmPelsHeight = pPresentationParameters->BackBufferHeight;
1394 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1395 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1397 /* For GetDisplayMode */
1398 This->ddraw_width = devmode.dmPelsWidth;
1399 This->ddraw_height = devmode.dmPelsHeight;
1400 This->ddraw_format = pPresentationParameters->BackBufferFormat;
1402 IWineD3DDevice_SetFullscreen(iface, TRUE);
1404 /* And finally clip mouse to our screen */
1405 SetRect(&clip_rc, 0, 0, devmode.dmPelsWidth, devmode.dmPelsHeight);
1406 ClipCursor(&clip_rc);
1409 /*********************
1410 * Create the back, front and stencil buffers
1411 *******************/
1412 if(object->presentParms.BackBufferCount > 0) {
1415 object->backBuffer = HeapAlloc(GetProcessHeap(), 0, sizeof(IWineD3DSurface *) * object->presentParms.BackBufferCount);
1416 if(!object->backBuffer) {
1417 ERR("Out of memory\n");
1422 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1423 TRACE("calling rendertarget CB\n");
1424 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1426 object->presentParms.BackBufferWidth,
1427 object->presentParms.BackBufferHeight,
1428 object->presentParms.BackBufferFormat,
1429 object->presentParms.MultiSampleType,
1430 object->presentParms.MultiSampleQuality,
1431 TRUE /* Lockable */,
1432 &object->backBuffer[i],
1433 NULL /* pShared (always null)*/);
1434 if(hr == WINED3D_OK && object->backBuffer[i]) {
1435 IWineD3DSurface_SetContainer(object->backBuffer[i], (IWineD3DBase *)object);
1437 ERR("Cannot create new back buffer\n");
1441 glDrawBuffer(GL_BACK);
1442 checkGLcall("glDrawBuffer(GL_BACK)");
1446 object->backBuffer = NULL;
1448 /* Single buffering - draw to front buffer */
1450 glDrawBuffer(GL_FRONT);
1451 checkGLcall("glDrawBuffer(GL_FRONT)");
1455 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1456 if (pPresentationParameters->EnableAutoDepthStencil && hr == WINED3D_OK) {
1457 TRACE("Creating depth stencil buffer\n");
1458 if (This->depthStencilBuffer == NULL ) {
1459 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1461 object->presentParms.BackBufferWidth,
1462 object->presentParms.BackBufferHeight,
1463 object->presentParms.AutoDepthStencilFormat,
1464 object->presentParms.MultiSampleType,
1465 object->presentParms.MultiSampleQuality,
1466 FALSE /* FIXME: Discard */,
1467 &This->depthStencilBuffer,
1468 NULL /* pShared (always null)*/ );
1469 if (This->depthStencilBuffer != NULL)
1470 IWineD3DSurface_SetContainer(This->depthStencilBuffer, 0);
1473 /** TODO: A check on width, height and multisample types
1474 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1475 ****************************/
1476 object->wantsDepthStencilBuffer = TRUE;
1478 object->wantsDepthStencilBuffer = FALSE;
1481 TRACE("Created swapchain %p\n", object);
1482 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer ? object->backBuffer[0] : NULL, object->wantsDepthStencilBuffer);
1486 if (object->backBuffer) {
1488 for(i = 0; i < object->presentParms.BackBufferCount; i++) {
1489 if(object->backBuffer[i]) {
1490 IWineD3DSurface_GetParent(object->backBuffer[i], &bufferParent);
1491 IUnknown_Release(bufferParent); /* once for the get parent */
1492 if (IUnknown_Release(bufferParent) > 0) {
1493 FIXME("(%p) Something's still holding the back buffer\n",This);
1497 HeapFree(GetProcessHeap(), 0, object->backBuffer);
1498 object->backBuffer = NULL;
1500 if(object->context) {
1501 DestroyContext(This, object->context);
1503 if(object->frontBuffer) {
1504 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1505 IUnknown_Release(bufferParent); /* once for the get parent */
1506 if (IUnknown_Release(bufferParent) > 0) {
1507 FIXME("(%p) Something's still holding the front buffer\n",This);
1510 if(object) HeapFree(GetProcessHeap(), 0, object);
1514 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1515 static UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1516 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1517 TRACE("(%p)\n", This);
1519 return This->NumberOfSwapChains;
1522 static HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1523 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1524 TRACE("(%p) : swapchain %d\n", This, iSwapChain);
1526 if(iSwapChain < This->NumberOfSwapChains) {
1527 *pSwapChain = This->swapchains[iSwapChain];
1528 IWineD3DSwapChain_AddRef(*pSwapChain);
1529 TRACE("(%p) returning %p\n", This, *pSwapChain);
1532 TRACE("Swapchain out of range\n");
1534 return WINED3DERR_INVALIDCALL;
1539 * Vertex Declaration
1541 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppVertexDeclaration,
1542 IUnknown *parent, const WINED3DVERTEXELEMENT *elements, size_t element_count) {
1543 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1544 IWineD3DVertexDeclarationImpl *object = NULL;
1545 HRESULT hr = WINED3D_OK;
1547 TRACE("(%p) : directXVersion %u, elements %p, element_count %d, ppDecl=%p\n",
1548 This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, elements, element_count, ppVertexDeclaration);
1550 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1553 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, elements, element_count);
1558 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1559 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, IWineD3DVertexDeclaration *vertex_declaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1560 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1561 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1562 HRESULT hr = WINED3D_OK;
1563 D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1564 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1566 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1568 if (vertex_declaration) {
1569 IWineD3DVertexShader_FakeSemantics(*ppVertexShader, vertex_declaration);
1572 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1574 if (WINED3D_OK != hr) {
1575 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1576 IWineD3DVertexShader_Release(*ppVertexShader);
1577 return WINED3DERR_INVALIDCALL;
1583 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1584 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1585 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1586 HRESULT hr = WINED3D_OK;
1588 D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
1589 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1590 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1591 if (WINED3D_OK == hr) {
1592 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1594 WARN("(%p) : Failed to create pixel shader\n", This);
1600 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1602 IWineD3DPaletteImpl *object;
1604 TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1606 /* Create the new object */
1607 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1609 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1610 return E_OUTOFMEMORY;
1613 object->lpVtbl = &IWineD3DPalette_Vtbl;
1615 object->Flags = Flags;
1616 object->parent = Parent;
1617 object->wineD3DDevice = This;
1618 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1620 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1623 HeapFree( GetProcessHeap(), 0, object);
1624 return E_OUTOFMEMORY;
1627 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1629 IWineD3DPalette_Release((IWineD3DPalette *) object);
1633 *Palette = (IWineD3DPalette *) object;
1638 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1639 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1640 IWineD3DSwapChainImpl *swapchain;
1643 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1644 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1646 /* TODO: Test if OpenGL is compiled in and loaded */
1648 /* Initialize the texture unit mapping to a 1:1 mapping */
1649 for(state = 0; state < MAX_SAMPLERS; state++) {
1650 This->texUnitMap[state] = state;
1652 This->oneToOneTexUnitMap = TRUE;
1654 /* Setup the implicit swapchain */
1655 TRACE("Creating implicit swapchain\n");
1656 if (FAILED(D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain)) || !swapchain) {
1657 WARN("Failed to create implicit swapchain\n");
1658 return WINED3DERR_INVALIDCALL;
1661 This->NumberOfSwapChains = 1;
1662 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1663 if(!This->swapchains) {
1664 ERR("Out of memory!\n");
1665 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1666 return E_OUTOFMEMORY;
1668 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1670 if(!This->ddraw_window) IWineD3DDevice_SetHWND(iface, swapchain->win_handle);
1672 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
1673 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1674 This->render_targets[0] = swapchain->backBuffer[0];
1675 This->lastActiveRenderTarget = swapchain->backBuffer[0];
1678 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1679 This->render_targets[0] = swapchain->frontBuffer;
1680 This->lastActiveRenderTarget = swapchain->frontBuffer;
1682 IWineD3DSurface_AddRef(This->render_targets[0]);
1683 This->activeContext = swapchain->context;
1685 /* Depth Stencil support */
1686 This->stencilBufferTarget = This->depthStencilBuffer;
1687 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
1688 set_depth_stencil_fbo(iface, This->depthStencilBuffer);
1690 if (NULL != This->stencilBufferTarget) {
1691 IWineD3DSurface_AddRef(This->stencilBufferTarget);
1694 /* Set up some starting GL setup */
1697 * Initialize openGL extension related variables
1698 * with Default values
1701 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->context->display);
1702 /* Setup all the devices defaults */
1703 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1705 IWineD3DImpl_CheckGraphicsMemory();
1708 { /* Set a default viewport */
1712 vp.Width = pPresentationParameters->BackBufferWidth;
1713 vp.Height = pPresentationParameters->BackBufferHeight;
1716 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1719 /* Initialize the current view state */
1720 This->view_ident = 1;
1721 This->contexts[0]->last_was_rhw = 0;
1722 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1723 checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
1725 switch(wined3d_settings.offscreen_rendering_mode) {
1728 This->offscreenBuffer = GL_BACK;
1731 case ORM_BACKBUFFER:
1733 if(GL_LIMITS(aux_buffers) > 0) {
1734 TRACE("Using auxilliary buffer for offscreen rendering\n");
1735 This->offscreenBuffer = GL_AUX0;
1737 TRACE("Using back buffer for offscreen rendering\n");
1738 This->offscreenBuffer = GL_BACK;
1743 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1746 /* Clear the screen */
1747 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL,
1748 WINED3DCLEAR_TARGET | pPresentationParameters->EnableAutoDepthStencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0,
1751 This->d3d_initialized = TRUE;
1755 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
1756 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1759 TRACE("(%p)\n", This);
1761 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1763 /* Delete the pbuffer context if there is any */
1764 if(This->pbufferContext) DestroyContext(This, This->pbufferContext);
1766 /* Delete the mouse cursor texture */
1767 if(This->cursorTexture) {
1769 glDeleteTextures(1, &This->cursorTexture);
1771 This->cursorTexture = 0;
1774 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
1775 IWineD3DDevice_SetTexture(iface, sampler, NULL);
1778 /* Release the buffers (with sanity checks)*/
1779 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1780 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1781 if(This->depthStencilBuffer != This->stencilBufferTarget)
1782 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1784 This->stencilBufferTarget = NULL;
1786 TRACE("Releasing the render target at %p\n", This->render_targets[0]);
1787 if(IWineD3DSurface_Release(This->render_targets[0]) >0){
1788 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1790 TRACE("Setting rendertarget to NULL\n");
1791 This->render_targets[0] = NULL;
1793 if (This->depthStencilBuffer) {
1794 if(D3DCB_DestroyDepthStencilSurface(This->depthStencilBuffer) > 0) {
1795 FIXME("(%p) Something's still holding the depthStencilBuffer\n", This);
1797 This->depthStencilBuffer = NULL;
1800 for(i=0; i < This->NumberOfSwapChains; i++) {
1801 TRACE("Releasing the implicit swapchain %d\n", i);
1802 if (D3DCB_DestroySwapChain(This->swapchains[i]) > 0) {
1803 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1807 HeapFree(GetProcessHeap(), 0, This->swapchains);
1808 This->swapchains = NULL;
1809 This->NumberOfSwapChains = 0;
1811 This->d3d_initialized = FALSE;
1815 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
1816 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1817 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
1819 /* Setup the window for fullscreen mode */
1820 if(fullscreen && !This->ddraw_fullscreen) {
1821 IWineD3DDeviceImpl_SetupFullscreenWindow(iface, This->ddraw_window);
1822 } else if(!fullscreen && This->ddraw_fullscreen) {
1823 IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
1826 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
1827 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
1828 * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
1831 This->ddraw_fullscreen = fullscreen;
1834 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1836 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1838 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
1841 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1843 /* Resize the screen even without a window:
1844 * The app could have unset it with SetCooperativeLevel, but not called
1845 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1846 * but we don't have any hwnd
1849 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1850 devmode.dmBitsPerPel = formatDesc->bpp * 8;
1851 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
1852 devmode.dmPelsWidth = pMode->Width;
1853 devmode.dmPelsHeight = pMode->Height;
1855 devmode.dmDisplayFrequency = pMode->RefreshRate;
1856 if (pMode->RefreshRate != 0) {
1857 devmode.dmFields |= DM_DISPLAYFREQUENCY;
1860 /* Only change the mode if necessary */
1861 if( (This->ddraw_width == pMode->Width) &&
1862 (This->ddraw_height == pMode->Height) &&
1863 (This->ddraw_format == pMode->Format) &&
1864 (pMode->RefreshRate == 0) ) {
1868 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
1869 if (ret != DISP_CHANGE_SUCCESSFUL) {
1870 if(devmode.dmDisplayFrequency != 0) {
1871 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
1872 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
1873 devmode.dmDisplayFrequency = 0;
1874 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
1876 if(ret != DISP_CHANGE_SUCCESSFUL) {
1877 return DDERR_INVALIDMODE;
1881 /* Store the new values */
1882 This->ddraw_width = pMode->Width;
1883 This->ddraw_height = pMode->Height;
1884 This->ddraw_format = pMode->Format;
1886 /* Only do this with a window of course */
1887 if(This->ddraw_window)
1888 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
1890 /* And finally clip mouse to our screen */
1891 SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height);
1892 ClipCursor(&clip_rc);
1897 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1898 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1899 *ppD3D= This->wineD3D;
1900 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1901 IWineD3D_AddRef(*ppD3D);
1905 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1906 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
1907 * into the video ram as possible and seeing how many fit
1908 * you can also get the correct initial value from nvidia and ATI's driver via X
1909 * texture memory is video memory + AGP memory
1910 *******************/
1911 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1912 static BOOL showfixmes = TRUE;
1914 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
1915 (wined3d_settings.emulated_textureram/(1024*1024)),
1916 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1919 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
1920 (wined3d_settings.emulated_textureram/(1024*1024)),
1921 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1922 /* return simulated texture memory left */
1923 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1931 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1932 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1934 /* Update the current state block */
1935 This->updateStateBlock->changed.fvf = TRUE;
1936 This->updateStateBlock->set.fvf = TRUE;
1938 if(This->updateStateBlock->fvf == fvf) {
1939 TRACE("Application is setting the old fvf over, nothing to do\n");
1943 This->updateStateBlock->fvf = fvf;
1944 TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
1945 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
1950 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1951 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1952 TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
1953 *pfvf = This->stateBlock->fvf;
1958 * Get / Set Stream Source
1960 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1961 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1962 IWineD3DVertexBuffer *oldSrc;
1964 if (StreamNumber >= MAX_STREAMS) {
1965 WARN("Stream out of range %d\n", StreamNumber);
1966 return WINED3DERR_INVALIDCALL;
1969 oldSrc = This->stateBlock->streamSource[StreamNumber];
1970 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1972 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1973 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1975 if(oldSrc == pStreamData &&
1976 This->updateStateBlock->streamStride[StreamNumber] == Stride &&
1977 This->updateStateBlock->streamOffset[StreamNumber] == OffsetInBytes) {
1978 TRACE("Application is setting the old values over, nothing to do\n");
1982 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1984 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1985 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1988 /* Handle recording of state blocks */
1989 if (This->isRecordingState) {
1990 TRACE("Recording... not performing anything\n");
1994 /* Need to do a getParent and pass the reffs up */
1995 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1996 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1997 so for now, just count internally */
1998 if (pStreamData != NULL) {
1999 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
2000 InterlockedIncrement(&vbImpl->bindCount);
2002 if (oldSrc != NULL) {
2003 InterlockedDecrement(&((IWineD3DVertexBufferImpl *) oldSrc)->bindCount);
2006 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2011 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2012 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2014 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2015 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2017 if (StreamNumber >= MAX_STREAMS) {
2018 WARN("Stream out of range %d\n", StreamNumber);
2019 return WINED3DERR_INVALIDCALL;
2021 *pStream = This->stateBlock->streamSource[StreamNumber];
2022 *pStride = This->stateBlock->streamStride[StreamNumber];
2024 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2027 if (*pStream != NULL) {
2028 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2033 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2034 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2035 UINT oldFlags = This->updateStateBlock->streamFlags[StreamNumber];
2036 UINT oldFreq = This->updateStateBlock->streamFreq[StreamNumber];
2038 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2039 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA );
2041 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2042 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2043 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2045 if(This->updateStateBlock->streamFreq[StreamNumber] != oldFreq ||
2046 This->updateStateBlock->streamFlags[StreamNumber] != oldFlags) {
2047 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2053 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2054 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2056 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2057 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2059 TRACE("(%p) : returning %d\n", This, *Divider);
2065 * Get / Set & Multiply Transform
2067 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2068 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2070 /* Most of this routine, comments included copied from ddraw tree initially: */
2071 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2073 /* Handle recording of state blocks */
2074 if (This->isRecordingState) {
2075 TRACE("Recording... not performing anything\n");
2076 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2077 This->updateStateBlock->set.transform[d3dts] = TRUE;
2078 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2083 * If the new matrix is the same as the current one,
2084 * we cut off any further processing. this seems to be a reasonable
2085 * optimization because as was noticed, some apps (warcraft3 for example)
2086 * tend towards setting the same matrix repeatedly for some reason.
2088 * From here on we assume that the new matrix is different, wherever it matters.
2090 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2091 TRACE("The app is setting the same matrix over again\n");
2094 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2098 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2099 where ViewMat = Camera space, WorldMat = world space.
2101 In OpenGL, camera and world space is combined into GL_MODELVIEW
2102 matrix. The Projection matrix stay projection matrix.
2105 /* Capture the times we can just ignore the change for now */
2106 if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2107 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2108 /* Handled by the state manager */
2111 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2115 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2116 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2117 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2118 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2122 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2123 WINED3DMATRIX *mat = NULL;
2126 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2127 * below means it will be recorded in a state block change, but it
2128 * works regardless where it is recorded.
2129 * If this is found to be wrong, change to StateBlock.
2131 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2132 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2134 if (State < HIGHEST_TRANSFORMSTATE)
2136 mat = &This->updateStateBlock->transforms[State];
2138 FIXME("Unhandled transform state!!\n");
2141 multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2143 /* Apply change via set transform - will reapply to eg. lights this way */
2144 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2150 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2151 you can reference any indexes you want as long as that number max are enabled at any
2152 one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2153 However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2154 but when recording, just build a chain pretty much of commands to be replayed. */
2156 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2158 PLIGHTINFOEL *object = NULL;
2159 UINT Hi = LIGHTMAP_HASHFUNC(Index);
2162 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2163 TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This, Index, pLight, Hi);
2165 /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2169 WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2170 return WINED3DERR_INVALIDCALL;
2173 switch(pLight->Type) {
2174 case WINED3DLIGHT_POINT:
2175 case WINED3DLIGHT_SPOT:
2176 case WINED3DLIGHT_PARALLELPOINT:
2177 case WINED3DLIGHT_GLSPOT:
2178 /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2181 if(pLight->Attenuation0 < 0.0 || pLight->Attenuation1 < 0.0 || pLight->Attenuation2 < 0.0) {
2182 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2183 return WINED3DERR_INVALIDCALL;
2187 case WINED3DLIGHT_DIRECTIONAL:
2188 /* Ignores attenuation */
2192 WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2193 return WINED3DERR_INVALIDCALL;
2196 LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2197 object = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2198 if(object->OriginalIndex == Index) break;
2203 TRACE("Adding new light\n");
2204 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2206 ERR("Out of memory error when allocating a light\n");
2207 return E_OUTOFMEMORY;
2209 list_add_head(&This->updateStateBlock->lightMap[Hi], &object->entry);
2210 object->glIndex = -1;
2211 object->OriginalIndex = Index;
2212 object->changed = TRUE;
2215 /* Initialize the object */
2216 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,
2217 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2218 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2219 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2220 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2221 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2222 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2224 /* Save away the information */
2225 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2227 switch (pLight->Type) {
2228 case WINED3DLIGHT_POINT:
2230 object->lightPosn[0] = pLight->Position.x;
2231 object->lightPosn[1] = pLight->Position.y;
2232 object->lightPosn[2] = pLight->Position.z;
2233 object->lightPosn[3] = 1.0f;
2234 object->cutoff = 180.0f;
2238 case WINED3DLIGHT_DIRECTIONAL:
2240 object->lightPosn[0] = -pLight->Direction.x;
2241 object->lightPosn[1] = -pLight->Direction.y;
2242 object->lightPosn[2] = -pLight->Direction.z;
2243 object->lightPosn[3] = 0.0;
2244 object->exponent = 0.0f;
2245 object->cutoff = 180.0f;
2248 case WINED3DLIGHT_SPOT:
2250 object->lightPosn[0] = pLight->Position.x;
2251 object->lightPosn[1] = pLight->Position.y;
2252 object->lightPosn[2] = pLight->Position.z;
2253 object->lightPosn[3] = 1.0;
2256 object->lightDirn[0] = pLight->Direction.x;
2257 object->lightDirn[1] = pLight->Direction.y;
2258 object->lightDirn[2] = pLight->Direction.z;
2259 object->lightDirn[3] = 1.0;
2262 * opengl-ish and d3d-ish spot lights use too different models for the
2263 * light "intensity" as a function of the angle towards the main light direction,
2264 * so we only can approximate very roughly.
2265 * however spot lights are rather rarely used in games (if ever used at all).
2266 * furthermore if still used, probably nobody pays attention to such details.
2268 if (pLight->Falloff == 0) {
2271 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2273 if (rho < 0.0001) rho = 0.0001f;
2274 object->exponent = -0.3/log(cos(rho/2));
2275 if (object->exponent > 128.0) {
2276 object->exponent = 128.0;
2278 object->cutoff = pLight->Phi*90/M_PI;
2284 FIXME("Unrecognized light type %d\n", pLight->Type);
2287 /* Update the live definitions if the light is currently assigned a glIndex */
2288 if (object->glIndex != -1 && !This->isRecordingState) {
2289 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(object->glIndex));
2294 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2295 PLIGHTINFOEL *lightInfo = NULL;
2296 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2297 DWORD Hi = LIGHTMAP_HASHFUNC(Index);
2299 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2301 LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2302 lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2303 if(lightInfo->OriginalIndex == Index) break;
2307 if (lightInfo == NULL) {
2308 TRACE("Light information requested but light not defined\n");
2309 return WINED3DERR_INVALIDCALL;
2312 memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2317 * Get / Set Light Enable
2318 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2320 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2321 PLIGHTINFOEL *lightInfo = NULL;
2322 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2323 UINT Hi = LIGHTMAP_HASHFUNC(Index);
2325 TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2327 /* Tests show true = 128...not clear why */
2328 Enable = Enable? 128: 0;
2330 LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2331 lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2332 if(lightInfo->OriginalIndex == Index) break;
2335 TRACE("Found light: %p\n", lightInfo);
2337 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2338 if (lightInfo == NULL) {
2340 TRACE("Light enabled requested but light not defined, so defining one!\n");
2341 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2343 /* Search for it again! Should be fairly quick as near head of list */
2344 LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2345 lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2346 if(lightInfo->OriginalIndex == Index) break;
2349 if (lightInfo == NULL) {
2350 FIXME("Adding default lights has failed dismally\n");
2351 return WINED3DERR_INVALIDCALL;
2355 lightInfo->enabledChanged = TRUE;
2357 if(lightInfo->glIndex != -1) {
2358 if(!This->isRecordingState) {
2359 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(lightInfo->glIndex));
2362 This->stateBlock->activeLights[lightInfo->glIndex] = NULL;
2363 lightInfo->glIndex = -1;
2365 TRACE("Light already disabled, nothing to do\n");
2368 if (lightInfo->glIndex != -1) {
2370 TRACE("Nothing to do as light was enabled\n");
2373 /* Find a free gl light */
2374 for(i = 0; i < This->maxConcurrentLights; i++) {
2375 if(This->stateBlock->activeLights[i] == NULL) {
2376 This->stateBlock->activeLights[i] = lightInfo;
2377 lightInfo->glIndex = i;
2381 if(lightInfo->glIndex == -1) {
2382 ERR("Too many concurrently active lights\n");
2383 return WINED3DERR_INVALIDCALL;
2386 /* i == lightInfo->glIndex */
2387 if(!This->isRecordingState) {
2388 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(i));
2396 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2398 PLIGHTINFOEL *lightInfo = NULL;
2399 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2401 UINT Hi = LIGHTMAP_HASHFUNC(Index);
2402 TRACE("(%p) : for idx(%d)\n", This, Index);
2404 LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2405 lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2406 if(lightInfo->OriginalIndex == Index) break;
2410 if (lightInfo == NULL) {
2411 TRACE("Light enabled state requested but light not defined\n");
2412 return WINED3DERR_INVALIDCALL;
2414 /* true is 128 according to SetLightEnable */
2415 *pEnable = lightInfo->glIndex != -1 ? 128 : 0;
2420 * Get / Set Clip Planes
2422 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2423 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2424 TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
2426 /* Validate Index */
2427 if (Index >= GL_LIMITS(clipplanes)) {
2428 TRACE("Application has requested clipplane this device doesn't support\n");
2429 return WINED3DERR_INVALIDCALL;
2432 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2433 This->updateStateBlock->set.clipplane[Index] = TRUE;
2435 if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] &&
2436 This->updateStateBlock->clipplane[Index][1] == pPlane[1] &&
2437 This->updateStateBlock->clipplane[Index][2] == pPlane[2] &&
2438 This->updateStateBlock->clipplane[Index][3] == pPlane[3]) {
2439 TRACE("Application is setting old values over, nothing to do\n");
2443 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2444 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2445 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2446 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2448 /* Handle recording of state blocks */
2449 if (This->isRecordingState) {
2450 TRACE("Recording... not performing anything\n");
2454 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_CLIPPLANE(Index));
2459 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2460 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2461 TRACE("(%p) : for idx %d\n", This, Index);
2463 /* Validate Index */
2464 if (Index >= GL_LIMITS(clipplanes)) {
2465 TRACE("Application has requested clipplane this device doesn't support\n");
2466 return WINED3DERR_INVALIDCALL;
2469 pPlane[0] = This->stateBlock->clipplane[Index][0];
2470 pPlane[1] = This->stateBlock->clipplane[Index][1];
2471 pPlane[2] = This->stateBlock->clipplane[Index][2];
2472 pPlane[3] = This->stateBlock->clipplane[Index][3];
2477 * Get / Set Clip Plane Status
2478 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2480 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2481 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2482 FIXME("(%p) : stub\n", This);
2483 if (NULL == pClipStatus) {
2484 return WINED3DERR_INVALIDCALL;
2486 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2487 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2491 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2492 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2493 FIXME("(%p) : stub\n", This);
2494 if (NULL == pClipStatus) {
2495 return WINED3DERR_INVALIDCALL;
2497 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2498 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2503 * Get / Set Material
2505 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2506 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2508 This->updateStateBlock->changed.material = TRUE;
2509 This->updateStateBlock->set.material = TRUE;
2510 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2512 /* Handle recording of state blocks */
2513 if (This->isRecordingState) {
2514 TRACE("Recording... not performing anything\n");
2519 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2520 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2521 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2522 pMaterial->Ambient.b, pMaterial->Ambient.a);
2523 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2524 pMaterial->Specular.b, pMaterial->Specular.a);
2525 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2526 pMaterial->Emissive.b, pMaterial->Emissive.a);
2527 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2529 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2530 checkGLcall("glMaterialfv(GL_AMBIENT)");
2531 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2532 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2534 /* Only change material color if specular is enabled, otherwise it is set to black */
2535 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2536 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2537 checkGLcall("glMaterialfv(GL_SPECULAR");
2539 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2540 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2541 checkGLcall("glMaterialfv(GL_SPECULAR");
2543 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2544 checkGLcall("glMaterialfv(GL_EMISSION)");
2545 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2546 checkGLcall("glMaterialf(GL_SHININESS");
2552 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2553 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2554 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2555 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2556 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2557 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2558 pMaterial->Ambient.b, pMaterial->Ambient.a);
2559 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2560 pMaterial->Specular.b, pMaterial->Specular.a);
2561 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2562 pMaterial->Emissive.b, pMaterial->Emissive.a);
2563 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2571 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2572 UINT BaseVertexIndex) {
2573 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2574 IWineD3DIndexBuffer *oldIdxs;
2575 UINT oldBaseIndex = This->updateStateBlock->baseVertexIndex;
2577 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2578 oldIdxs = This->updateStateBlock->pIndexData;
2580 This->updateStateBlock->changed.indices = TRUE;
2581 This->updateStateBlock->set.indices = TRUE;
2582 This->updateStateBlock->pIndexData = pIndexData;
2583 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2585 /* Handle recording of state blocks */
2586 if (This->isRecordingState) {
2587 TRACE("Recording... not performing anything\n");
2591 /* The base vertex index affects the stream sources, while
2592 * The index buffer is a seperate index buffer state
2594 if(BaseVertexIndex != oldBaseIndex) {
2595 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2597 if(oldIdxs != pIndexData) {
2598 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
2603 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2604 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2606 *ppIndexData = This->stateBlock->pIndexData;
2608 /* up ref count on ppindexdata */
2610 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2611 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2612 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2614 TRACE("(%p) No index data set\n", This);
2616 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2621 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
2622 static HRESULT WINAPI IWineD3DDeviceImpl_SetBasevertexIndex(IWineD3DDevice *iface, UINT BaseIndex) {
2623 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2624 TRACE("(%p)->(%d)\n", This, BaseIndex);
2626 if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
2627 TRACE("Application is setting the old value over, nothing to do\n");
2631 This->updateStateBlock->baseVertexIndex = BaseIndex;
2633 if (This->isRecordingState) {
2634 TRACE("Recording... not performing anything\n");
2637 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2642 * Get / Set Viewports
2644 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2645 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2647 TRACE("(%p)\n", This);
2648 This->updateStateBlock->changed.viewport = TRUE;
2649 This->updateStateBlock->set.viewport = TRUE;
2650 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2652 /* Handle recording of state blocks */
2653 if (This->isRecordingState) {
2654 TRACE("Recording... not performing anything\n");
2658 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
2659 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2661 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
2666 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2667 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2668 TRACE("(%p)\n", This);
2669 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2674 * Get / Set Render States
2675 * TODO: Verify against dx9 definitions
2677 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
2679 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2680 DWORD oldValue = This->stateBlock->renderState[State];
2682 TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
2684 This->updateStateBlock->changed.renderState[State] = TRUE;
2685 This->updateStateBlock->set.renderState[State] = TRUE;
2686 This->updateStateBlock->renderState[State] = Value;
2688 /* Handle recording of state blocks */
2689 if (This->isRecordingState) {
2690 TRACE("Recording... not performing anything\n");
2694 /* Compared here and not before the assignment to allow proper stateblock recording */
2695 if(Value == oldValue) {
2696 TRACE("Application is setting the old value over, nothing to do\n");
2698 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
2704 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
2705 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2706 TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
2707 *pValue = This->stateBlock->renderState[State];
2712 * Get / Set Sampler States
2713 * TODO: Verify against dx9 definitions
2716 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
2717 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2718 DWORD oldValue = This->stateBlock->samplerState[Sampler][Type];
2721 * SetSampler is designed to allow for more than the standard up to 8 textures
2722 * and Geforce has stopped supporting more than 6 standard textures in openGL.
2723 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
2725 * http://developer.nvidia.com/object/General_FAQ.html#t6
2727 * There are two new settings for GForce
2729 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
2730 * and the texture one:
2731 * GL_MAX_TEXTURE_COORDS_ARB.
2732 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
2735 TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
2736 debug_d3dsamplerstate(Type), Type, Value);
2737 This->updateStateBlock->samplerState[Sampler][Type] = Value;
2738 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
2739 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
2741 /* Handle recording of state blocks */
2742 if (This->isRecordingState) {
2743 TRACE("Recording... not performing anything\n");
2747 if(oldValue == Value) {
2748 TRACE("Application is setting the old value over, nothing to do\n");
2752 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
2757 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
2758 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2759 *Value = This->stateBlock->samplerState[Sampler][Type];
2760 TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
2765 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
2766 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2768 This->updateStateBlock->set.scissorRect = TRUE;
2769 This->updateStateBlock->changed.scissorRect = TRUE;
2770 if(EqualRect(&This->updateStateBlock->scissorRect, pRect)) {
2771 TRACE("App is setting the old scissor rectangle over, nothing to do\n");
2774 CopyRect(&This->updateStateBlock->scissorRect, pRect);
2776 if(This->isRecordingState) {
2777 TRACE("Recording... not performing anything\n");
2781 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
2786 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
2787 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2789 memcpy(pRect, &This->updateStateBlock->scissorRect, sizeof(pRect));
2790 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2794 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
2795 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2796 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
2798 TRACE("(%p) : pDecl=%p\n", This, pDecl);
2800 This->updateStateBlock->vertexDecl = pDecl;
2801 This->updateStateBlock->changed.vertexDecl = TRUE;
2802 This->updateStateBlock->set.vertexDecl = TRUE;
2804 if (This->isRecordingState) {
2805 TRACE("Recording... not performing anything\n");
2807 } else if(pDecl == oldDecl) {
2808 /* Checked after the assignment to allow proper stateblock recording */
2809 TRACE("Application is setting the old declaration over, nothing to do\n");
2813 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
2817 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
2818 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2820 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
2822 *ppDecl = This->stateBlock->vertexDecl;
2823 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
2827 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
2828 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2829 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
2831 This->updateStateBlock->vertexShader = pShader;
2832 This->updateStateBlock->changed.vertexShader = TRUE;
2833 This->updateStateBlock->set.vertexShader = TRUE;
2835 if (This->isRecordingState) {
2836 TRACE("Recording... not performing anything\n");
2838 } else if(oldShader == pShader) {
2839 /* Checked here to allow proper stateblock recording */
2840 TRACE("App is setting the old shader over, nothing to do\n");
2844 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
2846 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
2851 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
2852 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2854 if (NULL == ppShader) {
2855 return WINED3DERR_INVALIDCALL;
2857 *ppShader = This->stateBlock->vertexShader;
2858 if( NULL != *ppShader)
2859 IWineD3DVertexShader_AddRef(*ppShader);
2861 TRACE("(%p) : returning %p\n", This, *ppShader);
2865 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
2866 IWineD3DDevice *iface,
2868 CONST BOOL *srcData,
2871 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2872 int i, cnt = min(count, MAX_CONST_B - start);
2874 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2875 iface, srcData, start, count);
2877 if (srcData == NULL || cnt < 0)
2878 return WINED3DERR_INVALIDCALL;
2880 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
2881 for (i = 0; i < cnt; i++)
2882 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
2884 for (i = start; i < cnt + start; ++i) {
2885 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
2886 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
2889 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
2894 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
2895 IWineD3DDevice *iface,
2900 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2901 int cnt = min(count, MAX_CONST_B - start);
2903 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2904 iface, dstData, start, count);
2906 if (dstData == NULL || cnt < 0)
2907 return WINED3DERR_INVALIDCALL;
2909 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
2913 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
2914 IWineD3DDevice *iface,
2919 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2920 int i, cnt = min(count, MAX_CONST_I - start);
2922 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2923 iface, srcData, start, count);
2925 if (srcData == NULL || cnt < 0)
2926 return WINED3DERR_INVALIDCALL;
2928 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
2929 for (i = 0; i < cnt; i++)
2930 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
2931 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
2933 for (i = start; i < cnt + start; ++i) {
2934 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
2935 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
2938 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
2943 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
2944 IWineD3DDevice *iface,
2949 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2950 int cnt = min(count, MAX_CONST_I - start);
2952 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2953 iface, dstData, start, count);
2955 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
2956 return WINED3DERR_INVALIDCALL;
2958 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
2962 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
2963 IWineD3DDevice *iface,
2965 CONST float *srcData,
2968 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2971 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2972 iface, srcData, start, count);
2974 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
2975 if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
2976 return WINED3DERR_INVALIDCALL;
2978 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
2980 for (i = 0; i < count; i++)
2981 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
2982 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
2985 for (i = start; i < count + start; ++i) {
2986 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
2987 constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_vconstantsF), constants_entry, entry);
2988 if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
2989 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
2990 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
2992 ptr->idx[ptr->count++] = i;
2993 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
2995 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
2998 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3003 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3004 IWineD3DDevice *iface,
3009 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3010 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3012 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3013 iface, dstData, start, count);
3015 if (dstData == NULL || cnt < 0)
3016 return WINED3DERR_INVALIDCALL;
3018 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3022 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3024 for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
3025 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3029 static void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3031 /* This code can assume that GL_NV_register_combiners are supported, otherwise
3032 * it is never called.
3035 * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3036 * that would be really messy and require shader recompilation
3037 * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3038 * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3039 * -> Whith a 1:1 mapping oneToOneTexUnitMap is set to avoid checking MAX_SAMPLERS array
3040 * entries to make pixel shaders cheaper. MAX_SAMPLERS will be 128 in dx10
3042 if(This->stateBlock->pixelShader || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) {
3043 if(This->oneToOneTexUnitMap) {
3044 TRACE("Not touching 1:1 map\n");
3047 TRACE("Restoring 1:1 texture unit mapping\n");
3048 /* Restore a 1:1 mapping */
3049 for(i = 0; i < MAX_SAMPLERS; i++) {
3050 if(This->texUnitMap[i] != i) {
3051 This->texUnitMap[i] = i;
3052 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3053 markTextureStagesDirty(This, i);
3056 This->oneToOneTexUnitMap = TRUE;
3059 /* No pixel shader, and we do not have enough texture units available. Try to skip NULL textures
3060 * First, see if we can succeed at all
3063 for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3064 if(This->stateBlock->textures[i] == NULL) tex++;
3067 if(GL_LIMITS(textures) + tex < This->stateBlock->lowest_disabled_stage) {
3068 FIXME("Too many bound textures to support the combiner settings\n");
3072 /* Now work out the mapping */
3074 This->oneToOneTexUnitMap = FALSE;
3075 WARN("Non 1:1 mapping UNTESTED!\n");
3076 for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3077 /* Skip NULL textures */
3078 if (!This->stateBlock->textures[i]) {
3079 /* Map to -1, so the check below doesn't fail if a non-NULL
3080 * texture is set on this stage */
3081 TRACE("Mapping texture stage %d to -1\n", i);
3082 This->texUnitMap[i] = -1;
3087 TRACE("Mapping texture stage %d to unit %d\n", i, tex);
3088 if(This->texUnitMap[i] != tex) {
3089 This->texUnitMap[i] = tex;
3090 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3091 markTextureStagesDirty(This, i);
3099 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3100 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3101 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
3102 This->updateStateBlock->pixelShader = pShader;
3103 This->updateStateBlock->changed.pixelShader = TRUE;
3104 This->updateStateBlock->set.pixelShader = TRUE;
3106 /* Handle recording of state blocks */
3107 if (This->isRecordingState) {
3108 TRACE("Recording... not performing anything\n");
3111 if (This->isRecordingState) {
3112 TRACE("Recording... not performing anything\n");
3116 if(pShader == oldShader) {
3117 TRACE("App is setting the old pixel shader over, nothing to do\n");
3121 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3122 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3124 /* Rebuild the texture unit mapping if nvrc's are supported */
3125 if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3126 IWineD3DDeviceImpl_FindTexUnitMap(This);
3132 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3133 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3135 if (NULL == ppShader) {
3136 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3137 return WINED3DERR_INVALIDCALL;
3140 *ppShader = This->stateBlock->pixelShader;
3141 if (NULL != *ppShader) {
3142 IWineD3DPixelShader_AddRef(*ppShader);
3144 TRACE("(%p) : returning %p\n", This, *ppShader);
3148 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3149 IWineD3DDevice *iface,
3151 CONST BOOL *srcData,
3154 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3155 int i, cnt = min(count, MAX_CONST_B - start);
3157 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3158 iface, srcData, start, count);
3160 if (srcData == NULL || cnt < 0)
3161 return WINED3DERR_INVALIDCALL;
3163 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3164 for (i = 0; i < cnt; i++)
3165 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3167 for (i = start; i < cnt + start; ++i) {
3168 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3169 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
3172 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3177 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3178 IWineD3DDevice *iface,
3183 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3184 int cnt = min(count, MAX_CONST_B - start);
3186 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3187 iface, dstData, start, count);
3189 if (dstData == NULL || cnt < 0)
3190 return WINED3DERR_INVALIDCALL;
3192 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3196 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3197 IWineD3DDevice *iface,
3202 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3203 int i, cnt = min(count, MAX_CONST_I - start);
3205 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3206 iface, srcData, start, count);
3208 if (srcData == NULL || cnt < 0)
3209 return WINED3DERR_INVALIDCALL;
3211 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3212 for (i = 0; i < cnt; i++)
3213 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3214 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3216 for (i = start; i < cnt + start; ++i) {
3217 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3218 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
3221 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3226 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3227 IWineD3DDevice *iface,
3232 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3233 int cnt = min(count, MAX_CONST_I - start);
3235 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3236 iface, dstData, start, count);
3238 if (dstData == NULL || cnt < 0)
3239 return WINED3DERR_INVALIDCALL;
3241 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3245 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3246 IWineD3DDevice *iface,
3248 CONST float *srcData,
3251 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3254 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3255 iface, srcData, start, count);
3257 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3258 if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
3259 return WINED3DERR_INVALIDCALL;
3261 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3263 for (i = 0; i < count; i++)
3264 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3265 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3268 for (i = start; i < count + start; ++i) {
3269 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3270 constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_pconstantsF), constants_entry, entry);
3271 if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
3272 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
3273 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3275 ptr->idx[ptr->count++] = i;
3276 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3278 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3281 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3286 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3287 IWineD3DDevice *iface,
3292 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3293 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3295 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3296 iface, dstData, start, count);
3298 if (dstData == NULL || cnt < 0)
3299 return WINED3DERR_INVALIDCALL;
3301 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3305 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3307 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3308 char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
3310 DWORD DestFVF = dest->fvf;
3312 WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3316 if (SrcFVF & WINED3DFVF_NORMAL) {
3317 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3320 if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
3321 ERR("Source has no position mask\n");
3322 return WINED3DERR_INVALIDCALL;
3325 /* We might access VBOs from this code, so hold the lock */
3328 if (dest->resource.allocatedMemory == NULL) {
3329 /* This may happen if we do direct locking into a vbo. Unlikely,
3330 * but theoretically possible(ddraw processvertices test)
3332 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3333 if(!dest->resource.allocatedMemory) {
3335 ERR("Out of memory\n");
3336 return E_OUTOFMEMORY;
3340 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3341 checkGLcall("glBindBufferARB");
3342 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3344 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3346 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3347 checkGLcall("glUnmapBufferARB");
3351 /* Get a pointer into the destination vbo(create one if none exists) and
3352 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3354 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3359 dest_conv_addr = HeapAlloc(GetProcessHeap(), 0, dwCount * get_flexible_vertex_size(DestFVF));
3360 if(!dest_conv_addr) {
3361 ERR("Out of memory\n");
3362 /* Continue without storing converted vertices */
3364 dest_conv = dest_conv_addr;
3368 * a) WINED3DRS_CLIPPING is enabled
3369 * b) WINED3DVOP_CLIP is passed
3371 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3372 static BOOL warned = FALSE;
3374 * The clipping code is not quite correct. Some things need
3375 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3376 * so disable clipping for now.
3377 * (The graphics in Half-Life are broken, and my processvertices
3378 * test crashes with IDirect3DDevice3)
3384 FIXME("Clipping is broken and disabled for now\n");
3386 } else doClip = FALSE;
3387 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3389 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3392 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3393 WINED3DTS_PROJECTION,
3395 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3396 WINED3DTS_WORLDMATRIX(0),
3399 TRACE("View mat:\n");
3400 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);
3401 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);
3402 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);
3403 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);
3405 TRACE("Proj mat:\n");
3406 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);
3407 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);
3408 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);
3409 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);
3411 TRACE("World mat:\n");
3412 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);
3413 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);
3414 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);
3415 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);
3417 /* Get the viewport */
3418 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3419 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3420 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3422 multiply_matrix(&mat,&view_mat,&world_mat);
3423 multiply_matrix(&mat,&proj_mat,&mat);
3425 numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3427 for (i = 0; i < dwCount; i+= 1) {
3428 unsigned int tex_index;
3430 if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3431 ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3432 /* The position first */
3434 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
3436 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3438 /* Multiplication with world, view and projection matrix */
3439 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);
3440 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);
3441 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);
3442 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);
3444 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3446 /* WARNING: The following things are taken from d3d7 and were not yet checked
3447 * against d3d8 or d3d9!
3450 /* Clipping conditions: From
3451 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
3453 * A vertex is clipped if it does not match the following requirements
3457 * 0 < rhw ( Not in d3d7, but tested in d3d7)
3459 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3460 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3465 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3466 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
3469 /* "Normal" viewport transformation (not clipped)
3470 * 1) The values are divided by rhw
3471 * 2) The y axis is negative, so multiply it with -1
3472 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3473 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3474 * 4) Multiply x with Width/2 and add Width/2
3475 * 5) The same for the height
3476 * 6) Add the viewpoint X and Y to the 2D coordinates and
3477 * The minimum Z value to z
3478 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3480 * Well, basically it's simply a linear transformation into viewport
3492 z *= vp.MaxZ - vp.MinZ;
3494 x += vp.Width / 2 + vp.X;
3495 y += vp.Height / 2 + vp.Y;
3500 /* That vertex got clipped
3501 * Contrary to OpenGL it is not dropped completely, it just
3502 * undergoes a different calculation.
3504 TRACE("Vertex got clipped\n");
3511 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3512 * outside of the main vertex buffer memory. That needs some more
3517 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3520 ( (float *) dest_ptr)[0] = x;
3521 ( (float *) dest_ptr)[1] = y;
3522 ( (float *) dest_ptr)[2] = z;
3523 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3525 dest_ptr += 3 * sizeof(float);
3527 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3528 dest_ptr += sizeof(float);
3533 ( (float *) dest_conv)[0] = x * w;
3534 ( (float *) dest_conv)[1] = y * w;
3535 ( (float *) dest_conv)[2] = z * w;
3536 ( (float *) dest_conv)[3] = w;
3538 dest_conv += 3 * sizeof(float);
3540 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3541 dest_conv += sizeof(float);
3545 if (DestFVF & WINED3DFVF_PSIZE) {
3546 dest_ptr += sizeof(DWORD);
3547 if(dest_conv) dest_conv += sizeof(DWORD);
3549 if (DestFVF & WINED3DFVF_NORMAL) {
3551 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
3552 /* AFAIK this should go into the lighting information */
3553 FIXME("Didn't expect the destination to have a normal\n");
3554 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3556 copy_and_next(dest_conv, normal, 3 * sizeof(float));
3560 if (DestFVF & WINED3DFVF_DIFFUSE) {
3562 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
3564 static BOOL warned = FALSE;
3567 ERR("No diffuse color in source, but destination has one\n");
3571 *( (DWORD *) dest_ptr) = 0xffffffff;
3572 dest_ptr += sizeof(DWORD);
3575 *( (DWORD *) dest_conv) = 0xffffffff;
3576 dest_conv += sizeof(DWORD);
3580 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3582 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
3583 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
3584 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
3585 dest_conv += sizeof(DWORD);
3590 if (DestFVF & WINED3DFVF_SPECULAR) {
3591 /* What's the color value in the feedback buffer? */
3593 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
3595 static BOOL warned = FALSE;
3598 ERR("No specular color in source, but destination has one\n");
3602 *( (DWORD *) dest_ptr) = 0xFF000000;
3603 dest_ptr += sizeof(DWORD);
3606 *( (DWORD *) dest_conv) = 0xFF000000;
3607 dest_conv += sizeof(DWORD);
3611 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3613 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
3614 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
3615 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
3616 dest_conv += sizeof(DWORD);
3621 for (tex_index = 0; tex_index < numTextures; tex_index++) {
3623 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
3624 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
3626 ERR("No source texture, but destination requests one\n");
3627 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3628 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3631 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3633 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3640 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3641 checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
3642 GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
3643 dwCount * get_flexible_vertex_size(DestFVF),
3645 checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
3646 HeapFree(GetProcessHeap(), 0, dest_conv_addr);
3653 #undef copy_and_next
3655 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3656 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3657 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
3658 WineDirect3DVertexStridedData strided;
3659 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
3662 WARN("NULL source vertex buffer\n");
3663 return WINED3DERR_INVALIDCALL;
3665 /* We don't need the source vbo because this buffer is only used as
3666 * a source for ProcessVertices. Avoid wasting resources by converting the
3667 * buffer and loading the VBO
3670 TRACE("Releasing the source vbo, it won't be needed\n");
3672 if(!SrcImpl->resource.allocatedMemory) {
3673 /* Rescue the data from the buffer */
3675 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
3676 if(!SrcImpl->resource.allocatedMemory) {
3677 ERR("Out of memory\n");
3678 return E_OUTOFMEMORY;
3682 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
3683 checkGLcall("glBindBufferARB");
3685 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3687 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
3690 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3691 checkGLcall("glUnmapBufferARB");
3696 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
3697 checkGLcall("glBindBufferARB");
3698 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
3699 checkGLcall("glDeleteBuffersARB");
3705 memset(&strided, 0, sizeof(strided));
3706 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0, 0);
3708 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
3712 * Get / Set Texture Stage States
3713 * TODO: Verify against dx9 definitions
3715 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3716 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3717 DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
3719 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3721 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3723 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3724 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3725 This->updateStateBlock->textureState[Stage][Type] = Value;
3727 if (This->isRecordingState) {
3728 TRACE("Recording... not performing anything\n");
3732 /* Checked after the assignments to allow proper stateblock recording */
3733 if(oldValue == Value) {
3734 TRACE("App is setting the old value over, nothing to do\n");
3738 if(Stage > This->stateBlock->lowest_disabled_stage &&
3739 StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
3740 /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
3741 * Changes in other states are important on disabled stages too
3746 if(Type == WINED3DTSS_COLOROP) {
3749 if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
3750 /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
3751 * they have to be disabled
3753 * The current stage is dirtified below.
3755 for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
3756 TRACE("Additionally dirtifying stage %d\n", i);
3757 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3759 This->stateBlock->lowest_disabled_stage = Stage;
3760 TRACE("New lowest disabled: %d\n", Stage);
3761 } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
3762 /* Previously disabled stage enabled. Stages above it may need enabling
3763 * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
3764 * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
3766 * Again stage Stage doesn't need to be dirtified here, it is handled below.
3769 for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
3770 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
3773 TRACE("Additionally dirtifying stage %d due to enable\n", i);
3774 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3776 This->stateBlock->lowest_disabled_stage = i;
3777 TRACE("New lowest disabled: %d\n", i);
3779 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3780 /* TODO: Built a stage -> texture unit mapping for register combiners */
3784 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
3786 /* Rebuild the stage -> gl texture unit mapping if register combiners are supported
3787 * If there is a pixel shader there will be a 1:1 mapping, no need to touch it. SetPixelShader
3788 * will call FindTexUnitMap too.
3790 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3791 IWineD3DDeviceImpl_FindTexUnitMap(This);
3796 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3797 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3798 TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3799 *pValue = This->updateStateBlock->textureState[Stage][Type];
3806 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3809 IWineD3DBaseTexture *oldTexture;
3811 oldTexture = This->updateStateBlock->textures[Stage];
3812 TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
3814 #if 0 /* TODO: check so vertex textures */
3815 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
3816 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
3821 if(pTexture != NULL) {
3822 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
3824 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
3825 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
3826 return WINED3DERR_INVALIDCALL;
3828 This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
3831 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
3832 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
3834 This->updateStateBlock->set.textures[Stage] = TRUE;
3835 This->updateStateBlock->changed.textures[Stage] = TRUE;
3836 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
3837 This->updateStateBlock->textures[Stage] = pTexture;
3839 /* Handle recording of state blocks */
3840 if (This->isRecordingState) {
3841 TRACE("Recording... not performing anything\n");
3845 if(oldTexture == pTexture) {
3846 TRACE("App is setting the same texture again, nothing to do\n");
3850 /** NOTE: MSDN says that setTexture increases the reference count,
3851 * and the the application nust set the texture back to null (or have a leaky application),
3852 * This means we should pass the refcount up to the parent
3853 *******************************/
3854 if (NULL != This->updateStateBlock->textures[Stage]) {
3855 IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
3856 ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
3858 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
3859 if(oldTexture == NULL && Stage < MAX_TEXTURES) {
3860 /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
3861 * so the COLOROP and ALPHAOP have to be dirtified.
3863 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
3864 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
3866 if(bindCount == 1) {
3867 new->baseTexture.sampler = Stage;
3869 /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
3873 if (NULL != oldTexture) {
3874 IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
3875 LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
3877 IWineD3DBaseTexture_Release(oldTexture);
3878 if(pTexture == NULL && Stage < MAX_TEXTURES) {
3879 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
3880 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
3883 if(bindCount && old->baseTexture.sampler == Stage) {
3885 /* Have to do a search for the other sampler(s) where the texture is bound to
3886 * Shouldn't happen as long as apps bind a texture only to one stage
3888 TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
3889 for(i = 0; i < GL_LIMITS(sampler_stages); i++) {
3890 if(This->updateStateBlock->textures[i] == oldTexture) {
3891 old->baseTexture.sampler = i;
3898 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
3900 /* Verify the texture unit mapping(and rebuild it if needed) if we use nvrcs and no
3901 * pixel shader is used
3903 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3904 IWineD3DDeviceImpl_FindTexUnitMap(This);
3910 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3911 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3912 TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
3914 *ppTexture=This->stateBlock->textures[Stage];
3916 IWineD3DBaseTexture_AddRef(*ppTexture);
3924 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
3925 IWineD3DSurface **ppBackBuffer) {
3926 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3927 IWineD3DSwapChain *swapChain;
3930 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3932 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
3933 if (hr == WINED3D_OK) {
3934 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
3935 IWineD3DSwapChain_Release(swapChain);
3937 *ppBackBuffer = NULL;
3942 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
3943 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3944 WARN("(%p) : stub, calling idirect3d for now\n", This);
3945 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
3948 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
3949 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3950 IWineD3DSwapChain *swapChain;
3953 if(iSwapChain > 0) {
3954 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
3955 if (hr == WINED3D_OK) {
3956 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
3957 IWineD3DSwapChain_Release(swapChain);
3959 FIXME("(%p) Error getting display mode\n", This);
3962 /* Don't read the real display mode,
3963 but return the stored mode instead. X11 can't change the color
3964 depth, and some apps are pretty angry if they SetDisplayMode from
3965 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
3967 Also don't relay to the swapchain because with ddraw it's possible
3968 that there isn't a swapchain at all */
3969 pMode->Width = This->ddraw_width;
3970 pMode->Height = This->ddraw_height;
3971 pMode->Format = This->ddraw_format;
3972 pMode->RefreshRate = 0;
3979 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
3980 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3981 TRACE("(%p)->(%p)\n", This, hWnd);
3983 if(This->ddraw_fullscreen) {
3984 if(This->ddraw_window && This->ddraw_window != hWnd) {
3985 IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
3987 if(hWnd && This->ddraw_window != hWnd) {
3988 IWineD3DDeviceImpl_SetupFullscreenWindow(iface, hWnd);
3992 This->ddraw_window = hWnd;
3996 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
3997 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3998 TRACE("(%p)->(%p)\n", This, hWnd);
4000 *hWnd = This->ddraw_window;
4005 * Stateblock related functions
4008 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4009 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4010 IWineD3DStateBlockImpl *object;
4011 HRESULT temp_result;
4014 TRACE("(%p)\n", This);
4016 if (This->isRecordingState) {
4017 return WINED3DERR_INVALIDCALL;
4020 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4021 if (NULL == object ) {
4022 FIXME("(%p)Error allocating memory for stateblock\n", This);
4023 return E_OUTOFMEMORY;
4025 TRACE("(%p) created object %p\n", This, object);
4026 object->wineD3DDevice= This;
4027 /** FIXME: object->parent = parent; **/
4028 object->parent = NULL;
4029 object->blockType = WINED3DSBT_ALL;
4031 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4033 for(i = 0; i < LIGHTMAP_SIZE; i++) {
4034 list_init(&object->lightMap[i]);
4037 temp_result = allocate_shader_constants(object);
4038 if (WINED3D_OK != temp_result)
4041 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4042 This->updateStateBlock = object;
4043 This->isRecordingState = TRUE;
4045 TRACE("(%p) recording stateblock %p\n",This , object);
4049 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4050 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4052 if (!This->isRecordingState) {
4053 FIXME("(%p) not recording! returning error\n", This);
4054 *ppStateBlock = NULL;
4055 return WINED3DERR_INVALIDCALL;
4058 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4059 This->isRecordingState = FALSE;
4060 This->updateStateBlock = This->stateBlock;
4061 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4062 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4063 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4068 * Scene related functions
4070 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4071 /* At the moment we have no need for any functionality at the beginning
4073 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4074 TRACE("(%p)\n", This);
4077 TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4078 return WINED3DERR_INVALIDCALL;
4080 This->inScene = TRUE;
4084 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4085 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4086 TRACE("(%p)\n", This);
4088 if(!This->inScene) {
4089 TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4090 return WINED3DERR_INVALIDCALL;
4094 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4096 checkGLcall("glFlush");
4099 This->inScene = FALSE;
4103 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4104 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4105 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4106 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4107 IWineD3DSwapChain *swapChain = NULL;
4109 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4111 TRACE("(%p) Presenting the frame\n", This);
4113 for(i = 0 ; i < swapchains ; i ++) {
4115 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4116 TRACE("presentinng chain %d, %p\n", i, swapChain);
4117 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4118 IWineD3DSwapChain_Release(swapChain);
4124 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4125 DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4126 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4128 GLbitfield glMask = 0;
4130 CONST WINED3DRECT* curRect;
4132 TRACE("(%p) Count (%d), pRects (%p), Flags (%x), Z (%f), Stencil (%d)\n", This,
4133 Count, pRects, Flags, Z, Stencil);
4135 if(Flags & (WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL) && This->stencilBufferTarget == NULL) {
4136 WARN("Clearing depth and/or stencil without a depth stencil buffer attached, returning WINED3DERR_INVALIDCALL\n");
4137 /* TODO: What about depth stencil buffers without stencil bits? */
4138 return WINED3DERR_INVALIDCALL;
4143 glEnable(GL_SCISSOR_TEST);
4144 checkGLcall("glEnable GL_SCISSOR_TEST");
4145 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
4146 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_SCISSORTESTENABLE));
4148 if (Count > 0 && pRects) {
4154 /* Only set the values up once, as they are not changing */
4155 if (Flags & WINED3DCLEAR_STENCIL) {
4156 glClearStencil(Stencil);
4157 checkGLcall("glClearStencil");
4158 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4159 glStencilMask(0xFFFFFFFF);
4162 if (Flags & WINED3DCLEAR_ZBUFFER) {
4163 glDepthMask(GL_TRUE);
4165 checkGLcall("glClearDepth");
4166 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4167 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZWRITEENABLE));
4170 if (Flags & WINED3DCLEAR_TARGET) {
4171 TRACE("Clearing screen with glClear to color %x\n", Color);
4172 glClearColor(D3DCOLOR_R(Color),
4176 checkGLcall("glClearColor");
4178 /* Clear ALL colors! */
4179 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4180 glMask = glMask | GL_COLOR_BUFFER_BIT;
4184 glScissor(This->stateBlock->viewport.X,
4185 (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
4186 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4187 This->stateBlock->viewport.Width,
4188 This->stateBlock->viewport.Height);
4189 checkGLcall("glScissor");
4191 checkGLcall("glClear");
4193 /* Now process each rect in turn */
4194 for (i = 0; i < Count; i++) {
4195 /* Note gl uses lower left, width/height */
4196 TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4197 curRect[i].x1, curRect[i].y1, curRect[i].x2, curRect[i].y2,
4198 curRect[i].x1, (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect[i].y2),
4199 curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4201 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
4202 * The rectangle is not cleared, no error is returned, but further rectanlges are
4203 * still cleared if they are valid
4205 if(curRect[i].x1 > curRect[i].x2 || curRect[i].y1 > curRect[i].y2) {
4206 TRACE("Rectangle with negative dimensions, ignoring\n");
4210 glScissor(curRect[i].x1, ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height - curRect[i].y2,
4211 curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4212 checkGLcall("glScissor");
4215 checkGLcall("glClear");
4219 /* Restore the old values (why..?) */
4220 if (Flags & WINED3DCLEAR_STENCIL) {
4221 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4223 if (Flags & WINED3DCLEAR_TARGET) {
4224 DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
4225 glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4226 mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4227 mask & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4228 mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4233 /* Dirtify the target surface for now. If the surface is locked regularily, and an up to date sysmem copy exists,
4234 * it is most likely more efficient to perform a clear on the sysmem copy too isntead of downloading it
4236 ((IWineD3DSurfaceImpl *)This->render_targets[0])->Flags |= SFLAG_GLDIRTY;
4243 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4244 UINT PrimitiveCount) {
4246 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4247 This->stateBlock->streamIsUP = FALSE;
4249 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4250 debug_d3dprimitivetype(PrimitiveType),
4251 StartVertex, PrimitiveCount);
4253 if(This->stateBlock->loadBaseVertexIndex != 0) {
4254 This->stateBlock->loadBaseVertexIndex = 0;
4255 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4257 /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4258 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4259 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4263 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4264 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4265 WINED3DPRIMITIVETYPE PrimitiveType,
4266 UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4268 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4270 IWineD3DIndexBuffer *pIB;
4271 WINED3DINDEXBUFFER_DESC IdxBufDsc;
4274 pIB = This->stateBlock->pIndexData;
4275 This->stateBlock->streamIsUP = FALSE;
4276 vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
4278 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
4279 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4280 minIndex, NumVertices, startIndex, primCount);
4282 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4283 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4289 if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4290 This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4291 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4294 drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
4295 idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4300 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4301 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4302 UINT VertexStreamZeroStride) {
4303 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4305 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4306 debug_d3dprimitivetype(PrimitiveType),
4307 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4309 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4310 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4311 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4312 This->stateBlock->streamIsUP = TRUE;
4313 This->stateBlock->loadBaseVertexIndex = 0;
4315 /* TODO: Only mark dirty if drawing from a different UP address */
4316 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4318 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4319 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4321 /* MSDN specifies stream zero settings must be set to NULL */
4322 This->stateBlock->streamStride[0] = 0;
4323 This->stateBlock->streamSource[0] = NULL;
4325 /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4326 * the new stream sources or use UP drawing again
4331 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4332 UINT MinVertexIndex, UINT NumVertices,
4333 UINT PrimitiveCount, CONST void* pIndexData,
4334 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4335 UINT VertexStreamZeroStride) {
4337 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4339 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4340 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4341 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4342 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4344 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4350 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4351 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4352 This->stateBlock->streamIsUP = TRUE;
4353 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4355 /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4356 This->stateBlock->baseVertexIndex = 0;
4357 This->stateBlock->loadBaseVertexIndex = 0;
4358 /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4359 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4360 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4362 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4364 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4365 This->stateBlock->streamSource[0] = NULL;
4366 This->stateBlock->streamStride[0] = 0;
4367 This->stateBlock->pIndexData = NULL;
4368 /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4369 * SetStreamSource to specify a vertex buffer
4375 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4376 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4378 /* Mark the state dirty until we have nicer tracking
4379 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4382 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4383 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4384 This->stateBlock->baseVertexIndex = 0;
4385 This->up_strided = DrawPrimStrideData;
4386 This->stateBlock->streamIsUP = TRUE;
4387 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
4388 This->up_strided = NULL;
4391 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4392 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4393 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4394 HRESULT hr = WINED3D_OK;
4395 WINED3DRESOURCETYPE sourceType;
4396 WINED3DRESOURCETYPE destinationType;
4399 /* TODO: think about moving the code into IWineD3DBaseTexture */
4401 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4403 /* verify that the source and destination textures aren't NULL */
4404 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4405 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4406 This, pSourceTexture, pDestinationTexture);
4407 hr = WINED3DERR_INVALIDCALL;
4410 if (pSourceTexture == pDestinationTexture) {
4411 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4412 This, pSourceTexture, pDestinationTexture);
4413 hr = WINED3DERR_INVALIDCALL;
4415 /* Verify that the source and destination textures are the same type */
4416 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4417 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4419 if (sourceType != destinationType) {
4420 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
4422 hr = WINED3DERR_INVALIDCALL;
4425 /* check that both textures have the identical numbers of levels */
4426 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4427 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4428 hr = WINED3DERR_INVALIDCALL;
4431 if (WINED3D_OK == hr) {
4433 /* Make sure that the destination texture is loaded */
4434 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4436 /* Update every surface level of the texture */
4437 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4439 switch (sourceType) {
4440 case WINED3DRTYPE_TEXTURE:
4442 IWineD3DSurface *srcSurface;
4443 IWineD3DSurface *destSurface;
4445 for (i = 0 ; i < levels ; ++i) {
4446 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
4447 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4448 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4449 IWineD3DSurface_Release(srcSurface);
4450 IWineD3DSurface_Release(destSurface);
4451 if (WINED3D_OK != hr) {
4452 WARN("(%p) : Call to update surface failed\n", This);
4458 case WINED3DRTYPE_CUBETEXTURE:
4460 IWineD3DSurface *srcSurface;
4461 IWineD3DSurface *destSurface;
4462 WINED3DCUBEMAP_FACES faceType;
4464 for (i = 0 ; i < levels ; ++i) {
4465 /* Update each cube face */
4466 for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4467 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
4468 if (WINED3D_OK != hr) {
4469 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4471 TRACE("Got srcSurface %p\n", srcSurface);
4473 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4474 if (WINED3D_OK != hr) {
4475 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4477 TRACE("Got desrSurface %p\n", 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);
4490 #if 0 /* TODO: Add support for volume textures */
4491 case WINED3DRTYPE_VOLUMETEXTURE:
4493 IWineD3DVolume srcVolume = NULL;
4494 IWineD3DSurface destVolume = NULL;
4496 for (i = 0 ; i < levels ; ++i) {
4497 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
4498 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4499 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4500 IWineD3DVolume_Release(srcSurface);
4501 IWineD3DVolume_Release(destSurface);
4502 if (WINED3D_OK != hr) {
4503 WARN("(%p) : Call to update volume failed\n", This);
4511 FIXME("(%p) : Unsupported source and destination type\n", This);
4512 hr = WINED3DERR_INVALIDCALL;
4519 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4520 IWineD3DSwapChain *swapChain;
4522 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4523 if(hr == WINED3D_OK) {
4524 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4525 IWineD3DSwapChain_Release(swapChain);
4530 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4531 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4532 /* return a sensible default */
4534 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
4535 FIXME("(%p) : stub\n", This);
4539 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4540 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4542 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4543 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4544 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4545 return WINED3DERR_INVALIDCALL;
4547 for (j = 0; j < 256; ++j) {
4548 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
4549 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4550 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
4551 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4553 TRACE("(%p) : returning\n", This);
4557 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4558 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4560 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4561 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4562 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4563 return WINED3DERR_INVALIDCALL;
4565 for (j = 0; j < 256; ++j) {
4566 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
4567 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4568 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
4569 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4571 TRACE("(%p) : returning\n", This);
4575 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4576 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4577 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4578 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4579 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4580 return WINED3DERR_INVALIDCALL;
4582 /*TODO: stateblocks */
4583 This->currentPalette = PaletteNumber;
4584 TRACE("(%p) : returning\n", This);
4588 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4590 if (PaletteNumber == NULL) {
4591 WARN("(%p) : returning Invalid Call\n", This);
4592 return WINED3DERR_INVALIDCALL;
4594 /*TODO: stateblocks */
4595 *PaletteNumber = This->currentPalette;
4596 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
4600 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4601 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4602 static BOOL showFixmes = TRUE;
4604 FIXME("(%p) : stub\n", This);
4608 This->softwareVertexProcessing = bSoftware;
4613 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4614 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4615 static BOOL showFixmes = TRUE;
4617 FIXME("(%p) : stub\n", This);
4620 return This->softwareVertexProcessing;
4624 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
4625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4626 IWineD3DSwapChain *swapChain;
4629 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4631 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4632 if(hr == WINED3D_OK){
4633 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4634 IWineD3DSwapChain_Release(swapChain);
4636 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
4642 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4644 static BOOL showfixmes = TRUE;
4645 if(nSegments != 0.0f) {
4647 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4654 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4656 static BOOL showfixmes = TRUE;
4658 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4664 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4665 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4666 /** TODO: remove casts to IWineD3DSurfaceImpl
4667 * NOTE: move code to surface to accomplish this
4668 ****************************************/
4669 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4670 int srcWidth, srcHeight;
4671 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4672 WINED3DFORMAT destFormat, srcFormat;
4674 int srcLeft, destLeft, destTop;
4675 WINED3DPOOL srcPool, destPool;
4677 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4678 glDescriptor *glDescription = NULL;
4680 WINED3DSURFACE_DESC winedesc;
4682 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
4683 memset(&winedesc, 0, sizeof(winedesc));
4684 winedesc.Width = &srcSurfaceWidth;
4685 winedesc.Height = &srcSurfaceHeight;
4686 winedesc.Pool = &srcPool;
4687 winedesc.Format = &srcFormat;
4689 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4691 winedesc.Width = &destSurfaceWidth;
4692 winedesc.Height = &destSurfaceHeight;
4693 winedesc.Pool = &destPool;
4694 winedesc.Format = &destFormat;
4695 winedesc.Size = &destSize;
4697 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4699 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
4700 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
4701 return WINED3DERR_INVALIDCALL;
4704 if (destFormat == WINED3DFMT_UNKNOWN) {
4705 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
4706 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
4708 /* Get the update surface description */
4709 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4713 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4714 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
4715 checkGLcall("glActiveTextureARB");
4718 /* Make sure the surface is loaded and up to date */
4719 IWineD3DSurface_PreLoad(pDestinationSurface);
4721 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4723 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4724 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4725 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4726 srcLeft = pSourceRect ? pSourceRect->left : 0;
4727 destLeft = pDestPoint ? pDestPoint->x : 0;
4728 destTop = pDestPoint ? pDestPoint->y : 0;
4731 /* This function doesn't support compressed textures
4732 the pitch is just bytesPerPixel * width */
4733 if(srcWidth != srcSurfaceWidth || srcLeft ){
4734 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4735 offset += srcLeft * pSrcSurface->bytesPerPixel;
4736 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4738 /* TODO DXT formats */
4740 if(pSourceRect != NULL && pSourceRect->top != 0){
4741 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4743 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4745 ,glDescription->level
4750 ,glDescription->glFormat
4751 ,glDescription->glType
4752 ,IWineD3DSurface_GetData(pSourceSurface)
4756 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4758 /* need to lock the surface to get the data */
4759 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4762 /* TODO: Cube and volume support */
4764 /* not a whole row so we have to do it a line at a time */
4767 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4768 const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4770 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4772 glTexSubImage2D(glDescription->target
4773 ,glDescription->level
4778 ,glDescription->glFormat
4779 ,glDescription->glType
4780 ,data /* could be quicker using */
4785 } else { /* Full width, so just write out the whole texture */
4787 if (WINED3DFMT_DXT1 == destFormat ||
4788 WINED3DFMT_DXT2 == destFormat ||
4789 WINED3DFMT_DXT3 == destFormat ||
4790 WINED3DFMT_DXT4 == destFormat ||
4791 WINED3DFMT_DXT5 == destFormat) {
4792 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4793 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4794 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
4795 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4796 } if (destFormat != srcFormat) {
4797 FIXME("Updating mixed format compressed texture is not curretly support\n");
4799 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4800 glDescription->level,
4801 glDescription->glFormatInternal,
4806 IWineD3DSurface_GetData(pSourceSurface));
4809 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4814 glTexSubImage2D(glDescription->target
4815 ,glDescription->level
4820 ,glDescription->glFormat
4821 ,glDescription->glType
4822 ,IWineD3DSurface_GetData(pSourceSurface)
4826 checkGLcall("glTexSubImage2D");
4830 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_GLDIRTY;
4831 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
4836 /* Implementation details at http://developer.nvidia.com/attach/6494
4838 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4839 hmm.. no longer supported use
4840 OpenGL evaluators or tessellate surfaces within your application.
4843 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4844 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
4845 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4846 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
4847 FIXME("(%p) : Stub\n", This);
4852 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4853 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
4854 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4855 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
4856 FIXME("(%p) : Stub\n", This);
4860 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4861 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4862 TRACE("(%p) Handle(%d)\n", This, Handle);
4863 FIXME("(%p) : Stub\n", This);
4867 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
4868 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4869 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
4871 TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
4873 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
4874 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
4875 return WINED3DERR_INVALIDCALL;
4878 /* Just forward this to the DirectDraw blitting engine */
4879 memset(&BltFx, 0, sizeof(BltFx));
4880 BltFx.dwSize = sizeof(BltFx);
4881 BltFx.u5.dwFillColor = color;
4882 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
4885 /* rendertarget and deptth stencil functions */
4886 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
4887 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4889 if (RenderTargetIndex >= GL_LIMITS(buffers)) {
4890 ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
4891 return WINED3DERR_INVALIDCALL;
4894 *ppRenderTarget = This->render_targets[RenderTargetIndex];
4895 TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4896 /* Note inc ref on returned surface */
4897 if(*ppRenderTarget != NULL)
4898 IWineD3DSurface_AddRef(*ppRenderTarget);
4902 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
4903 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4904 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
4905 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
4906 IWineD3DSwapChainImpl *Swapchain;
4909 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
4911 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
4912 if(hr != WINED3D_OK) {
4913 ERR("Can't get the swapchain\n");
4917 /* Make sure to release the swapchain */
4918 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
4920 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
4921 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
4922 return WINED3DERR_INVALIDCALL;
4924 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
4925 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
4926 return WINED3DERR_INVALIDCALL;
4929 if(Swapchain->frontBuffer != Front) {
4930 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
4932 if(Swapchain->frontBuffer)
4933 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
4934 Swapchain->frontBuffer = Front;
4936 if(Swapchain->frontBuffer) {
4937 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
4941 if(Back && !Swapchain->backBuffer) {
4942 /* We need memory for the back buffer array - only one back buffer this way */
4943 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
4944 if(!Swapchain->backBuffer) {
4945 ERR("Out of memory\n");
4946 return E_OUTOFMEMORY;
4950 if(Swapchain->backBuffer[0] != Back) {
4951 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
4953 if(!Swapchain->backBuffer[0]) {
4954 /* GL was told to draw to the front buffer at creation,
4957 glDrawBuffer(GL_BACK);
4958 checkGLcall("glDrawBuffer(GL_BACK)");
4959 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
4960 Swapchain->presentParms.BackBufferCount = 1;
4962 /* That makes problems - disable for now */
4963 /* glDrawBuffer(GL_FRONT); */
4964 checkGLcall("glDrawBuffer(GL_FRONT)");
4965 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
4966 Swapchain->presentParms.BackBufferCount = 0;
4970 if(Swapchain->backBuffer[0])
4971 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
4972 Swapchain->backBuffer[0] = Back;
4974 if(Swapchain->backBuffer[0]) {
4975 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
4977 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
4985 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
4986 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4987 *ppZStencilSurface = This->depthStencilBuffer;
4988 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
4990 if(*ppZStencilSurface != NULL) {
4991 /* Note inc ref on returned surface */
4992 IWineD3DSurface_AddRef(*ppZStencilSurface);
4997 static void bind_fbo(IWineD3DDevice *iface) {
4998 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5001 GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
5002 checkGLcall("glGenFramebuffersEXT()");
5004 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
5005 checkGLcall("glBindFramebuffer()");
5008 /* TODO: Handle stencil attachments */
5009 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5010 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5011 IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5013 This->depth_copy_state = WINED3D_DCS_NO_COPY;
5017 if (depth_stencil_impl) {
5018 GLenum texttarget, target;
5019 GLint old_binding = 0;
5021 IWineD3DSurface_PreLoad(depth_stencil);
5022 texttarget = depth_stencil_impl->glDescription.target;
5023 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5025 glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5026 glBindTexture(target, depth_stencil_impl->glDescription.textureName);
5027 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5028 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5029 glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5030 glBindTexture(target, old_binding);
5032 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5033 checkGLcall("glFramebufferTexture2DEXT()");
5035 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5036 checkGLcall("glFramebufferTexture2DEXT()");
5039 if (!This->render_offscreen) {
5040 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5041 checkGLcall("glBindFramebuffer()");
5045 void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5046 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5047 IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5049 if (idx >= GL_LIMITS(buffers)) {
5050 ERR("%p : Trying to set render target %d, but only %d supported\n", This, idx, GL_LIMITS(buffers));
5056 GLenum texttarget, target;
5057 GLint old_binding = 0;
5059 IWineD3DSurface_PreLoad(render_target);
5060 texttarget = rtimpl->glDescription.target;
5061 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5063 glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5064 glBindTexture(target, rtimpl->glDescription.textureName);
5065 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5066 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5067 glBindTexture(target, old_binding);
5069 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, rtimpl->glDescription.textureName, 0));
5070 checkGLcall("glFramebufferTexture2DEXT()");
5072 This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5074 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5075 checkGLcall("glFramebufferTexture2DEXT()");
5077 This->draw_buffers[idx] = GL_NONE;
5080 if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5081 GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5082 checkGLcall("glDrawBuffers()");
5085 if (!This->render_offscreen) {
5086 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5087 checkGLcall("glBindFramebuffer()");
5091 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5092 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5093 WINED3DVIEWPORT viewport;
5095 TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5097 if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5098 ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5099 return WINED3DERR_INVALIDCALL;
5102 /* MSDN says that null disables the render target
5103 but a device must always be associated with a render target
5104 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5106 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5109 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5110 FIXME("Trying to set render target 0 to NULL\n");
5111 return WINED3DERR_INVALIDCALL;
5113 if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5114 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);
5115 return WINED3DERR_INVALIDCALL;
5118 /* If we are trying to set what we already have, don't bother */
5119 if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5120 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5123 if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5124 if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5125 This->render_targets[RenderTargetIndex] = pRenderTarget;
5127 /* Render target 0 is special */
5128 if(RenderTargetIndex == 0) {
5129 /* Finally, reset the viewport as the MSDN states. */
5130 viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5131 viewport.Width = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5134 viewport.MaxZ = 1.0f;
5135 viewport.MinZ = 0.0f;
5136 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5138 /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
5140 * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
5141 * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
5143 ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
5145 /* We only get more than 1 render target with fbos, so no need to check the offscreen rendering method */
5146 set_render_target_fbo(iface, RenderTargetIndex, pRenderTarget);
5151 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5152 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5153 HRESULT hr = WINED3D_OK;
5154 IWineD3DSurface *tmp;
5156 TRACE("(%p) Swapping z-buffer\n",This);
5158 if (pNewZStencil == This->stencilBufferTarget) {
5159 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5161 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5162 * depending on the renter target implementation being used.
5163 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5164 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5165 * stencil buffer and incure an extra memory overhead
5166 ******************************************************/
5168 tmp = This->stencilBufferTarget;
5169 This->stencilBufferTarget = pNewZStencil;
5170 /* should we be calling the parent or the wined3d surface? */
5171 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5172 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5175 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5176 set_depth_stencil_fbo(iface, pNewZStencil);
5183 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5184 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5185 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5186 /* TODO: the use of Impl is deprecated. */
5187 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5189 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5191 /* some basic validation checks */
5192 if(This->cursorTexture) {
5194 glDeleteTextures(1, &This->cursorTexture);
5196 This->cursorTexture = 0;
5200 /* MSDN: Cursor must be A8R8G8B8 */
5201 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5202 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5203 return WINED3DERR_INVALIDCALL;
5206 /* MSDN: Cursor must be smaller than the display mode */
5207 if(pSur->currentDesc.Width > This->ddraw_width ||
5208 pSur->currentDesc.Height > This->ddraw_height) {
5209 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);
5210 return WINED3DERR_INVALIDCALL;
5213 /* TODO: MSDN: Cursor sizes must be a power of 2 */
5214 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
5215 * Texture and Blitting code to draw the cursor
5217 pSur->Flags |= SFLAG_FORCELOAD;
5218 IWineD3DSurface_PreLoad(pCursorBitmap);
5219 pSur->Flags &= ~SFLAG_FORCELOAD;
5220 /* Do not store the surface's pointer because the application may release
5221 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
5222 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
5224 This->cursorTexture = pSur->glDescription.textureName;
5225 This->cursorWidth = pSur->currentDesc.Width;
5226 This->cursorHeight = pSur->currentDesc.Height;
5227 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
5230 This->xHotSpot = XHotSpot;
5231 This->yHotSpot = YHotSpot;
5235 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5236 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5237 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5239 This->xScreenSpace = XScreenSpace;
5240 This->yScreenSpace = YScreenSpace;
5246 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5247 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5248 BOOL oldVisible = This->bCursorVisible;
5251 TRACE("(%p) : visible(%d)\n", This, bShow);
5253 if(This->cursorTexture)
5254 This->bCursorVisible = bShow;
5256 * When ShowCursor is first called it should make the cursor appear at the OS's last
5257 * known cursor position. Because of this, some applications just repetitively call
5258 * ShowCursor in order to update the cursor's position. This behavior is undocumented.
5261 This->xScreenSpace = pt.x;
5262 This->yScreenSpace = pt.y;
5267 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5268 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5269 TRACE("(%p) : state (%u)\n", This, This->state);
5270 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
5271 switch (This->state) {
5274 case WINED3DERR_DEVICELOST:
5276 ResourceList *resourceList = This->resources;
5277 while (NULL != resourceList) {
5278 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
5279 return WINED3DERR_DEVICENOTRESET;
5280 resourceList = resourceList->next;
5282 return WINED3DERR_DEVICELOST;
5284 case WINED3DERR_DRIVERINTERNALERROR:
5285 return WINED3DERR_DRIVERINTERNALERROR;
5289 return WINED3DERR_DRIVERINTERNALERROR;
5293 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5294 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5295 /** FIXME: Resource tracking needs to be done,
5296 * The closes we can do to this is set the priorities of all managed textures low
5297 * and then reset them.
5298 ***********************************************************/
5299 FIXME("(%p) : stub\n", This);
5303 void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5304 IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
5306 /* Reallocate proper memory for the front and back buffer and adjust their sizes */
5307 if(surface->Flags & SFLAG_DIBSECTION) {
5308 /* Release the DC */
5309 SelectObject(surface->hDC, surface->dib.holdbitmap);
5310 DeleteDC(surface->hDC);
5311 /* Release the DIB section */
5312 DeleteObject(surface->dib.DIBsection);
5313 surface->dib.bitmap_data = NULL;
5314 surface->resource.allocatedMemory = NULL;
5315 surface->Flags &= ~SFLAG_DIBSECTION;
5317 surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
5318 surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
5319 if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
5320 surface->pow2Width = pPresentationParameters->BackBufferWidth;
5321 surface->pow2Height = pPresentationParameters->BackBufferHeight;
5323 surface->pow2Width = surface->pow2Height = 1;
5324 while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
5325 while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
5327 if(surface->glDescription.textureName) {
5329 glDeleteTextures(1, &surface->glDescription.textureName);
5331 surface->glDescription.textureName = 0;
5333 if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
5334 surface->pow2Height != pPresentationParameters->BackBufferHeight) {
5335 surface->Flags |= SFLAG_NONPOW2;
5337 surface->Flags &= ~SFLAG_NONPOW2;
5339 HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
5340 surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
5343 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5344 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5345 IWineD3DSwapChainImpl *swapchain;
5347 BOOL DisplayModeChanged = FALSE;
5348 WINED3DDISPLAYMODE mode;
5349 TRACE("(%p)\n", This);
5351 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
5353 ERR("Failed to get the first implicit swapchain\n");
5357 /* Is it necessary to recreate the gl context? Actually every setting can be changed
5358 * on an existing gl context, so there's no real need for recreation.
5360 * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
5362 * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
5364 TRACE("New params:\n");
5365 TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
5366 TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
5367 TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
5368 TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
5369 TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
5370 TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
5371 TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
5372 TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
5373 TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
5374 TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
5375 TRACE("Flags = %08x\n", pPresentationParameters->Flags);
5376 TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
5377 TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
5379 /* No special treatment of these parameters. Just store them */
5380 swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
5381 swapchain->presentParms.Flags = pPresentationParameters->Flags;
5382 swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
5383 swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
5385 /* What to do about these? */
5386 if(pPresentationParameters->BackBufferCount != 0 &&
5387 pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
5388 ERR("Cannot change the back buffer count yet\n");
5390 if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
5391 pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
5392 ERR("Cannot change the back buffer format yet\n");
5394 if(pPresentationParameters->hDeviceWindow != NULL &&
5395 pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
5396 ERR("Cannot change the device window yet\n");
5398 if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
5399 ERR("What do do about a changed auto depth stencil parameter?\n");
5402 if(pPresentationParameters->Windowed) {
5403 mode.Width = swapchain->orig_width;
5404 mode.Height = swapchain->orig_height;
5405 mode.RefreshRate = 0;
5406 mode.Format = swapchain->presentParms.BackBufferFormat;
5408 mode.Width = pPresentationParameters->BackBufferWidth;
5409 mode.Height = pPresentationParameters->BackBufferHeight;
5410 mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
5411 mode.Format = swapchain->presentParms.BackBufferFormat;
5414 /* Should Width == 800 && Height == 0 set 800x600? */
5415 if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
5416 (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
5417 pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
5424 vp.Width = pPresentationParameters->BackBufferWidth;
5425 vp.Height = pPresentationParameters->BackBufferHeight;
5429 if(!pPresentationParameters->Windowed) {
5430 DisplayModeChanged = TRUE;
5432 swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
5433 swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
5435 updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
5436 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
5437 updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
5440 /* Now set the new viewport */
5441 IWineD3DDevice_SetViewport(iface, &vp);
5444 if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
5445 (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
5446 DisplayModeChanged) {
5448 /* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */
5449 if(!pPresentationParameters->Windowed) {
5450 IWineD3DDevice_SetFullscreen(iface, TRUE);
5453 IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
5455 /* Switching out of fullscreen mode? First set the original res, then change the window */
5456 if(pPresentationParameters->Windowed) {
5457 IWineD3DDevice_SetFullscreen(iface, FALSE);
5459 swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
5462 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
5466 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5467 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5468 /** FIXME: always true at the moment **/
5469 if(!bEnableDialogs) {
5470 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5476 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
5477 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5478 TRACE("(%p) : pParameters %p\n", This, pParameters);
5480 *pParameters = This->createParms;
5484 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
5485 IWineD3DSwapChain *swapchain;
5486 HRESULT hrc = WINED3D_OK;
5488 TRACE("Relaying to swapchain\n");
5490 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5491 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
5492 IWineD3DSwapChain_Release(swapchain);
5497 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
5498 IWineD3DSwapChain *swapchain;
5499 HRESULT hrc = WINED3D_OK;
5501 TRACE("Relaying to swapchain\n");
5503 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5504 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5505 IWineD3DSwapChain_Release(swapchain);
5511 /** ********************************************************
5512 * Notification functions
5513 ** ********************************************************/
5514 /** This function must be called in the release of a resource when ref == 0,
5515 * the contents of resource must still be correct,
5516 * any handels to other resource held by the caller must be closed
5517 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5518 *****************************************************/
5519 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5520 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5521 ResourceList* resourceList;
5523 TRACE("(%p) : resource %p\n", This, resource);
5525 EnterCriticalSection(&resourceStoreCriticalSection);
5527 /* add a new texture to the frot of the linked list */
5528 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5529 resourceList->resource = resource;
5531 /* Get the old head */
5532 resourceList->next = This->resources;
5534 This->resources = resourceList;
5535 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5538 LeaveCriticalSection(&resourceStoreCriticalSection);
5543 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5544 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5545 ResourceList* resourceList = NULL;
5546 ResourceList* previousResourceList = NULL;
5548 TRACE("(%p) : resource %p\n", This, resource);
5551 EnterCriticalSection(&resourceStoreCriticalSection);
5553 resourceList = This->resources;
5555 while (resourceList != NULL) {
5556 if(resourceList->resource == resource) break;
5557 previousResourceList = resourceList;
5558 resourceList = resourceList->next;
5561 if (resourceList == NULL) {
5562 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5564 LeaveCriticalSection(&resourceStoreCriticalSection);
5568 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5570 /* make sure we don't leave a hole in the list */
5571 if (previousResourceList != NULL) {
5572 previousResourceList->next = resourceList->next;
5574 This->resources = resourceList->next;
5578 LeaveCriticalSection(&resourceStoreCriticalSection);
5584 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5585 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5588 TRACE("(%p) : resource %p\n", This, resource);
5589 switch(IWineD3DResource_GetType(resource)){
5590 case WINED3DRTYPE_SURFACE:
5591 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5593 case WINED3DRTYPE_TEXTURE:
5594 case WINED3DRTYPE_CUBETEXTURE:
5595 case WINED3DRTYPE_VOLUMETEXTURE:
5596 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
5597 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5598 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5599 This->stateBlock->textures[counter] = NULL;
5601 if (This->updateStateBlock != This->stateBlock ){
5602 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5603 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5604 This->updateStateBlock->textures[counter] = NULL;
5609 case WINED3DRTYPE_VOLUME:
5610 /* TODO: nothing really? */
5612 case WINED3DRTYPE_VERTEXBUFFER:
5613 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5616 TRACE("Cleaning up stream pointers\n");
5618 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5619 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5620 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5622 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5623 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5624 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5625 This->updateStateBlock->streamSource[streamNumber] = 0;
5626 /* Set changed flag? */
5629 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) */
5630 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5631 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5632 This->stateBlock->streamSource[streamNumber] = 0;
5635 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5636 else { /* This shouldn't happen */
5637 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5644 case WINED3DRTYPE_INDEXBUFFER:
5645 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5646 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5647 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5648 This->updateStateBlock->pIndexData = NULL;
5651 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5652 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5653 This->stateBlock->pIndexData = NULL;
5659 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
5664 /* Remove the resoruce from the resourceStore */
5665 IWineD3DDeviceImpl_RemoveResource(iface, resource);
5667 TRACE("Resource released\n");
5671 /**********************************************************
5672 * IWineD3DDevice VTbl follows
5673 **********************************************************/
5675 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5677 /*** IUnknown methods ***/
5678 IWineD3DDeviceImpl_QueryInterface,
5679 IWineD3DDeviceImpl_AddRef,
5680 IWineD3DDeviceImpl_Release,
5681 /*** IWineD3DDevice methods ***/
5682 IWineD3DDeviceImpl_GetParent,
5683 /*** Creation methods**/
5684 IWineD3DDeviceImpl_CreateVertexBuffer,
5685 IWineD3DDeviceImpl_CreateIndexBuffer,
5686 IWineD3DDeviceImpl_CreateStateBlock,
5687 IWineD3DDeviceImpl_CreateSurface,
5688 IWineD3DDeviceImpl_CreateTexture,
5689 IWineD3DDeviceImpl_CreateVolumeTexture,
5690 IWineD3DDeviceImpl_CreateVolume,
5691 IWineD3DDeviceImpl_CreateCubeTexture,
5692 IWineD3DDeviceImpl_CreateQuery,
5693 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5694 IWineD3DDeviceImpl_CreateVertexDeclaration,
5695 IWineD3DDeviceImpl_CreateVertexShader,
5696 IWineD3DDeviceImpl_CreatePixelShader,
5697 IWineD3DDeviceImpl_CreatePalette,
5698 /*** Odd functions **/
5699 IWineD3DDeviceImpl_Init3D,
5700 IWineD3DDeviceImpl_Uninit3D,
5701 IWineD3DDeviceImpl_SetFullscreen,
5702 IWineD3DDeviceImpl_EvictManagedResources,
5703 IWineD3DDeviceImpl_GetAvailableTextureMem,
5704 IWineD3DDeviceImpl_GetBackBuffer,
5705 IWineD3DDeviceImpl_GetCreationParameters,
5706 IWineD3DDeviceImpl_GetDeviceCaps,
5707 IWineD3DDeviceImpl_GetDirect3D,
5708 IWineD3DDeviceImpl_GetDisplayMode,
5709 IWineD3DDeviceImpl_SetDisplayMode,
5710 IWineD3DDeviceImpl_GetHWND,
5711 IWineD3DDeviceImpl_SetHWND,
5712 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5713 IWineD3DDeviceImpl_GetRasterStatus,
5714 IWineD3DDeviceImpl_GetSwapChain,
5715 IWineD3DDeviceImpl_Reset,
5716 IWineD3DDeviceImpl_SetDialogBoxMode,
5717 IWineD3DDeviceImpl_SetCursorProperties,
5718 IWineD3DDeviceImpl_SetCursorPosition,
5719 IWineD3DDeviceImpl_ShowCursor,
5720 IWineD3DDeviceImpl_TestCooperativeLevel,
5721 /*** Getters and setters **/
5722 IWineD3DDeviceImpl_SetClipPlane,
5723 IWineD3DDeviceImpl_GetClipPlane,
5724 IWineD3DDeviceImpl_SetClipStatus,
5725 IWineD3DDeviceImpl_GetClipStatus,
5726 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5727 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5728 IWineD3DDeviceImpl_SetDepthStencilSurface,
5729 IWineD3DDeviceImpl_GetDepthStencilSurface,
5730 IWineD3DDeviceImpl_SetFVF,
5731 IWineD3DDeviceImpl_GetFVF,
5732 IWineD3DDeviceImpl_SetGammaRamp,
5733 IWineD3DDeviceImpl_GetGammaRamp,
5734 IWineD3DDeviceImpl_SetIndices,
5735 IWineD3DDeviceImpl_GetIndices,
5736 IWineD3DDeviceImpl_SetBasevertexIndex,
5737 IWineD3DDeviceImpl_SetLight,
5738 IWineD3DDeviceImpl_GetLight,
5739 IWineD3DDeviceImpl_SetLightEnable,
5740 IWineD3DDeviceImpl_GetLightEnable,
5741 IWineD3DDeviceImpl_SetMaterial,
5742 IWineD3DDeviceImpl_GetMaterial,
5743 IWineD3DDeviceImpl_SetNPatchMode,
5744 IWineD3DDeviceImpl_GetNPatchMode,
5745 IWineD3DDeviceImpl_SetPaletteEntries,
5746 IWineD3DDeviceImpl_GetPaletteEntries,
5747 IWineD3DDeviceImpl_SetPixelShader,
5748 IWineD3DDeviceImpl_GetPixelShader,
5749 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5750 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5751 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5752 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5753 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5754 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5755 IWineD3DDeviceImpl_SetRenderState,
5756 IWineD3DDeviceImpl_GetRenderState,
5757 IWineD3DDeviceImpl_SetRenderTarget,
5758 IWineD3DDeviceImpl_GetRenderTarget,
5759 IWineD3DDeviceImpl_SetFrontBackBuffers,
5760 IWineD3DDeviceImpl_SetSamplerState,
5761 IWineD3DDeviceImpl_GetSamplerState,
5762 IWineD3DDeviceImpl_SetScissorRect,
5763 IWineD3DDeviceImpl_GetScissorRect,
5764 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5765 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5766 IWineD3DDeviceImpl_SetStreamSource,
5767 IWineD3DDeviceImpl_GetStreamSource,
5768 IWineD3DDeviceImpl_SetStreamSourceFreq,
5769 IWineD3DDeviceImpl_GetStreamSourceFreq,
5770 IWineD3DDeviceImpl_SetTexture,
5771 IWineD3DDeviceImpl_GetTexture,
5772 IWineD3DDeviceImpl_SetTextureStageState,
5773 IWineD3DDeviceImpl_GetTextureStageState,
5774 IWineD3DDeviceImpl_SetTransform,
5775 IWineD3DDeviceImpl_GetTransform,
5776 IWineD3DDeviceImpl_SetVertexDeclaration,
5777 IWineD3DDeviceImpl_GetVertexDeclaration,
5778 IWineD3DDeviceImpl_SetVertexShader,
5779 IWineD3DDeviceImpl_GetVertexShader,
5780 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5781 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5782 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5783 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5784 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5785 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5786 IWineD3DDeviceImpl_SetViewport,
5787 IWineD3DDeviceImpl_GetViewport,
5788 IWineD3DDeviceImpl_MultiplyTransform,
5789 IWineD3DDeviceImpl_ValidateDevice,
5790 IWineD3DDeviceImpl_ProcessVertices,
5791 /*** State block ***/
5792 IWineD3DDeviceImpl_BeginStateBlock,
5793 IWineD3DDeviceImpl_EndStateBlock,
5794 /*** Scene management ***/
5795 IWineD3DDeviceImpl_BeginScene,
5796 IWineD3DDeviceImpl_EndScene,
5797 IWineD3DDeviceImpl_Present,
5798 IWineD3DDeviceImpl_Clear,
5800 IWineD3DDeviceImpl_DrawPrimitive,
5801 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5802 IWineD3DDeviceImpl_DrawPrimitiveUP,
5803 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5804 IWineD3DDeviceImpl_DrawPrimitiveStrided,
5805 IWineD3DDeviceImpl_DrawRectPatch,
5806 IWineD3DDeviceImpl_DrawTriPatch,
5807 IWineD3DDeviceImpl_DeletePatch,
5808 IWineD3DDeviceImpl_ColorFill,
5809 IWineD3DDeviceImpl_UpdateTexture,
5810 IWineD3DDeviceImpl_UpdateSurface,
5811 IWineD3DDeviceImpl_GetFrontBufferData,
5812 /*** object tracking ***/
5813 IWineD3DDeviceImpl_ResourceReleased
5817 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5818 WINED3DRS_ALPHABLENDENABLE ,
5819 WINED3DRS_ALPHAFUNC ,
5820 WINED3DRS_ALPHAREF ,
5821 WINED3DRS_ALPHATESTENABLE ,
5823 WINED3DRS_COLORWRITEENABLE ,
5824 WINED3DRS_DESTBLEND ,
5825 WINED3DRS_DITHERENABLE ,
5826 WINED3DRS_FILLMODE ,
5827 WINED3DRS_FOGDENSITY ,
5829 WINED3DRS_FOGSTART ,
5830 WINED3DRS_LASTPIXEL ,
5831 WINED3DRS_SHADEMODE ,
5832 WINED3DRS_SRCBLEND ,
5833 WINED3DRS_STENCILENABLE ,
5834 WINED3DRS_STENCILFAIL ,
5835 WINED3DRS_STENCILFUNC ,
5836 WINED3DRS_STENCILMASK ,
5837 WINED3DRS_STENCILPASS ,
5838 WINED3DRS_STENCILREF ,
5839 WINED3DRS_STENCILWRITEMASK ,
5840 WINED3DRS_STENCILZFAIL ,
5841 WINED3DRS_TEXTUREFACTOR ,
5852 WINED3DRS_ZWRITEENABLE
5855 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5856 WINED3DTSS_ADDRESSW ,
5857 WINED3DTSS_ALPHAARG0 ,
5858 WINED3DTSS_ALPHAARG1 ,
5859 WINED3DTSS_ALPHAARG2 ,
5860 WINED3DTSS_ALPHAOP ,
5861 WINED3DTSS_BUMPENVLOFFSET ,
5862 WINED3DTSS_BUMPENVLSCALE ,
5863 WINED3DTSS_BUMPENVMAT00 ,
5864 WINED3DTSS_BUMPENVMAT01 ,
5865 WINED3DTSS_BUMPENVMAT10 ,
5866 WINED3DTSS_BUMPENVMAT11 ,
5867 WINED3DTSS_COLORARG0 ,
5868 WINED3DTSS_COLORARG1 ,
5869 WINED3DTSS_COLORARG2 ,
5870 WINED3DTSS_COLOROP ,
5871 WINED3DTSS_RESULTARG ,
5872 WINED3DTSS_TEXCOORDINDEX ,
5873 WINED3DTSS_TEXTURETRANSFORMFLAGS
5876 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5877 WINED3DSAMP_ADDRESSU ,
5878 WINED3DSAMP_ADDRESSV ,
5879 WINED3DSAMP_ADDRESSW ,
5880 WINED3DSAMP_BORDERCOLOR ,
5881 WINED3DSAMP_MAGFILTER ,
5882 WINED3DSAMP_MINFILTER ,
5883 WINED3DSAMP_MIPFILTER ,
5884 WINED3DSAMP_MIPMAPLODBIAS ,
5885 WINED3DSAMP_MAXMIPLEVEL ,
5886 WINED3DSAMP_MAXANISOTROPY ,
5887 WINED3DSAMP_SRGBTEXTURE ,
5888 WINED3DSAMP_ELEMENTINDEX
5891 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5893 WINED3DRS_AMBIENTMATERIALSOURCE ,
5894 WINED3DRS_CLIPPING ,
5895 WINED3DRS_CLIPPLANEENABLE ,
5896 WINED3DRS_COLORVERTEX ,
5897 WINED3DRS_DIFFUSEMATERIALSOURCE ,
5898 WINED3DRS_EMISSIVEMATERIALSOURCE ,
5899 WINED3DRS_FOGDENSITY ,
5901 WINED3DRS_FOGSTART ,
5902 WINED3DRS_FOGTABLEMODE ,
5903 WINED3DRS_FOGVERTEXMODE ,
5904 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
5905 WINED3DRS_LIGHTING ,
5906 WINED3DRS_LOCALVIEWER ,
5907 WINED3DRS_MULTISAMPLEANTIALIAS ,
5908 WINED3DRS_MULTISAMPLEMASK ,
5909 WINED3DRS_NORMALIZENORMALS ,
5910 WINED3DRS_PATCHEDGESTYLE ,
5911 WINED3DRS_POINTSCALE_A ,
5912 WINED3DRS_POINTSCALE_B ,
5913 WINED3DRS_POINTSCALE_C ,
5914 WINED3DRS_POINTSCALEENABLE ,
5915 WINED3DRS_POINTSIZE ,
5916 WINED3DRS_POINTSIZE_MAX ,
5917 WINED3DRS_POINTSIZE_MIN ,
5918 WINED3DRS_POINTSPRITEENABLE ,
5919 WINED3DRS_RANGEFOGENABLE ,
5920 WINED3DRS_SPECULARMATERIALSOURCE ,
5921 WINED3DRS_TWEENFACTOR ,
5922 WINED3DRS_VERTEXBLEND
5925 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5926 WINED3DTSS_TEXCOORDINDEX ,
5927 WINED3DTSS_TEXTURETRANSFORMFLAGS
5930 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5931 WINED3DSAMP_DMAPOFFSET
5934 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
5935 DWORD rep = StateTable[state].representative;
5939 WineD3DContext *context;
5942 for(i = 0; i < This->numContexts; i++) {
5943 context = This->contexts[i];
5944 if(isStateDirty(context, rep)) continue;
5946 context->dirtyArray[context->numDirtyEntries++] = rep;
5949 context->isStateDirty[idx] |= (1 << shift);