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 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)
1552 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, elements, element_count);
1557 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1558 static HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice *iface, IWineD3DVertexDeclaration *vertex_declaration, CONST DWORD *pFunction, IWineD3DVertexShader **ppVertexShader, IUnknown *parent) {
1559 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1560 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1561 HRESULT hr = WINED3D_OK;
1562 D3DCREATESHADEROBJECTINSTANCE(object, VertexShader)
1563 object->baseShader.shader_ins = IWineD3DVertexShaderImpl_shader_ins;
1565 TRACE("(%p) : Created Vertex shader %p\n", This, *ppVertexShader);
1567 if (vertex_declaration) {
1568 IWineD3DVertexShader_FakeSemantics(*ppVertexShader, vertex_declaration);
1571 hr = IWineD3DVertexShader_SetFunction(*ppVertexShader, pFunction);
1573 if (WINED3D_OK != hr) {
1574 FIXME("(%p) : Failed to set the function, returning WINED3DERR_INVALIDCALL\n", iface);
1575 IWineD3DVertexShader_Release(*ppVertexShader);
1576 return WINED3DERR_INVALIDCALL;
1582 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice *iface, CONST DWORD *pFunction, IWineD3DPixelShader **ppPixelShader, IUnknown *parent) {
1583 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1584 IWineD3DPixelShaderImpl *object; /* NOTE: impl allowed, this is a create */
1585 HRESULT hr = WINED3D_OK;
1587 D3DCREATESHADEROBJECTINSTANCE(object, PixelShader)
1588 object->baseShader.shader_ins = IWineD3DPixelShaderImpl_shader_ins;
1589 hr = IWineD3DPixelShader_SetFunction(*ppPixelShader, pFunction);
1590 if (WINED3D_OK == hr) {
1591 TRACE("(%p) : Created Pixel shader %p\n", This, *ppPixelShader);
1593 WARN("(%p) : Failed to create pixel shader\n", This);
1599 static HRESULT WINAPI IWineD3DDeviceImpl_CreatePalette(IWineD3DDevice *iface, DWORD Flags, PALETTEENTRY *PalEnt, IWineD3DPalette **Palette, IUnknown *Parent) {
1600 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1601 IWineD3DPaletteImpl *object;
1603 TRACE("(%p)->(%x, %p, %p, %p)\n", This, Flags, PalEnt, Palette, Parent);
1605 /* Create the new object */
1606 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DPaletteImpl));
1608 ERR("Out of memory when allocating memory for a IWineD3DPalette implementation\n");
1609 return E_OUTOFMEMORY;
1612 object->lpVtbl = &IWineD3DPalette_Vtbl;
1614 object->Flags = Flags;
1615 object->parent = Parent;
1616 object->wineD3DDevice = This;
1617 object->palNumEntries = IWineD3DPaletteImpl_Size(Flags);
1619 object->hpal = CreatePalette((const LOGPALETTE*)&(object->palVersion));
1622 HeapFree( GetProcessHeap(), 0, object);
1623 return E_OUTOFMEMORY;
1626 hr = IWineD3DPalette_SetEntries((IWineD3DPalette *) object, 0, 0, IWineD3DPaletteImpl_Size(Flags), PalEnt);
1628 IWineD3DPalette_Release((IWineD3DPalette *) object);
1632 *Palette = (IWineD3DPalette *) object;
1637 static HRESULT WINAPI IWineD3DDeviceImpl_Init3D(IWineD3DDevice *iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, D3DCB_CREATEADDITIONALSWAPCHAIN D3DCB_CreateAdditionalSwapChain) {
1638 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1639 IWineD3DSwapChainImpl *swapchain;
1642 TRACE("(%p)->(%p,%p)\n", This, pPresentationParameters, D3DCB_CreateAdditionalSwapChain);
1643 if(This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1645 /* TODO: Test if OpenGL is compiled in and loaded */
1647 /* Initialize the texture unit mapping to a 1:1 mapping */
1648 for(state = 0; state < MAX_SAMPLERS; state++) {
1649 This->texUnitMap[state] = state;
1651 This->oneToOneTexUnitMap = TRUE;
1653 /* Setup the implicit swapchain */
1654 TRACE("Creating implicit swapchain\n");
1655 if (FAILED(D3DCB_CreateAdditionalSwapChain((IUnknown *) This->parent, pPresentationParameters, (IWineD3DSwapChain **)&swapchain)) || !swapchain) {
1656 WARN("Failed to create implicit swapchain\n");
1657 return WINED3DERR_INVALIDCALL;
1660 This->NumberOfSwapChains = 1;
1661 This->swapchains = HeapAlloc(GetProcessHeap(), 0, This->NumberOfSwapChains * sizeof(IWineD3DSwapChain *));
1662 if(!This->swapchains) {
1663 ERR("Out of memory!\n");
1664 IWineD3DSwapChain_Release( (IWineD3DSwapChain *) swapchain);
1665 return E_OUTOFMEMORY;
1667 This->swapchains[0] = (IWineD3DSwapChain *) swapchain;
1669 if(!This->ddraw_window) IWineD3DDevice_SetHWND(iface, swapchain->win_handle);
1671 if(swapchain->backBuffer && swapchain->backBuffer[0]) {
1672 TRACE("Setting rendertarget to %p\n", swapchain->backBuffer);
1673 This->render_targets[0] = swapchain->backBuffer[0];
1674 This->lastActiveRenderTarget = swapchain->backBuffer[0];
1677 TRACE("Setting rendertarget to %p\n", swapchain->frontBuffer);
1678 This->render_targets[0] = swapchain->frontBuffer;
1679 This->lastActiveRenderTarget = swapchain->frontBuffer;
1681 IWineD3DSurface_AddRef(This->render_targets[0]);
1682 This->activeContext = swapchain->context;
1684 /* Depth Stencil support */
1685 This->stencilBufferTarget = This->depthStencilBuffer;
1686 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
1687 set_depth_stencil_fbo(iface, This->depthStencilBuffer);
1689 if (NULL != This->stencilBufferTarget) {
1690 IWineD3DSurface_AddRef(This->stencilBufferTarget);
1693 /* Set up some starting GL setup */
1696 * Initialize openGL extension related variables
1697 * with Default values
1700 ((IWineD3DImpl *) This->wineD3D)->isGLInfoValid = IWineD3DImpl_FillGLCaps( This->wineD3D, swapchain->context->display);
1701 /* Setup all the devices defaults */
1702 IWineD3DStateBlock_InitStartupStateBlock((IWineD3DStateBlock *)This->stateBlock);
1704 IWineD3DImpl_CheckGraphicsMemory();
1707 { /* Set a default viewport */
1711 vp.Width = pPresentationParameters->BackBufferWidth;
1712 vp.Height = pPresentationParameters->BackBufferHeight;
1715 IWineD3DDevice_SetViewport((IWineD3DDevice *)This, &vp);
1718 /* Initialize the current view state */
1719 This->view_ident = 1;
1720 This->contexts[0]->last_was_rhw = 0;
1721 glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights);
1722 checkGLcall("glGetIntegerv(GL_MAX_LIGHTS, &This->maxConcurrentLights)");
1724 switch(wined3d_settings.offscreen_rendering_mode) {
1727 This->offscreenBuffer = GL_BACK;
1730 case ORM_BACKBUFFER:
1732 if(GL_LIMITS(aux_buffers) > 0) {
1733 TRACE("Using auxilliary buffer for offscreen rendering\n");
1734 This->offscreenBuffer = GL_AUX0;
1736 TRACE("Using back buffer for offscreen rendering\n");
1737 This->offscreenBuffer = GL_BACK;
1742 TRACE("(%p) All defaults now set up, leaving Init3D with %p\n", This, This);
1745 /* Clear the screen */
1746 IWineD3DDevice_Clear((IWineD3DDevice *) This, 0, NULL,
1747 WINED3DCLEAR_TARGET | pPresentationParameters->EnableAutoDepthStencil ? WINED3DCLEAR_ZBUFFER | WINED3DCLEAR_STENCIL : 0,
1750 This->d3d_initialized = TRUE;
1754 static HRESULT WINAPI IWineD3DDeviceImpl_Uninit3D(IWineD3DDevice *iface, D3DCB_DESTROYSURFACEFN D3DCB_DestroyDepthStencilSurface, D3DCB_DESTROYSWAPCHAINFN D3DCB_DestroySwapChain) {
1755 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1758 TRACE("(%p)\n", This);
1760 if(!This->d3d_initialized) return WINED3DERR_INVALIDCALL;
1762 /* Delete the pbuffer context if there is any */
1763 if(This->pbufferContext) DestroyContext(This, This->pbufferContext);
1765 /* Delete the mouse cursor texture */
1766 if(This->cursorTexture) {
1768 glDeleteTextures(1, &This->cursorTexture);
1770 This->cursorTexture = 0;
1773 for(sampler = 0; sampler < GL_LIMITS(sampler_stages); ++sampler) {
1774 IWineD3DDevice_SetTexture(iface, sampler, NULL);
1777 /* Release the buffers (with sanity checks)*/
1778 TRACE("Releasing the depth stencil buffer at %p\n", This->stencilBufferTarget);
1779 if(This->stencilBufferTarget != NULL && (IWineD3DSurface_Release(This->stencilBufferTarget) >0)){
1780 if(This->depthStencilBuffer != This->stencilBufferTarget)
1781 FIXME("(%p) Something's still holding the depthStencilBuffer\n",This);
1783 This->stencilBufferTarget = NULL;
1785 TRACE("Releasing the render target at %p\n", This->render_targets[0]);
1786 if(IWineD3DSurface_Release(This->render_targets[0]) >0){
1787 /* This check is a bit silly, itshould be in swapchain_release FIXME("(%p) Something's still holding the renderTarget\n",This); */
1789 TRACE("Setting rendertarget to NULL\n");
1790 This->render_targets[0] = NULL;
1792 if (This->depthStencilBuffer) {
1793 if(D3DCB_DestroyDepthStencilSurface(This->depthStencilBuffer) > 0) {
1794 FIXME("(%p) Something's still holding the depthStencilBuffer\n", This);
1796 This->depthStencilBuffer = NULL;
1799 for(i=0; i < This->NumberOfSwapChains; i++) {
1800 TRACE("Releasing the implicit swapchain %d\n", i);
1801 if (D3DCB_DestroySwapChain(This->swapchains[i]) > 0) {
1802 FIXME("(%p) Something's still holding the implicit swapchain\n", This);
1806 HeapFree(GetProcessHeap(), 0, This->swapchains);
1807 This->swapchains = NULL;
1808 This->NumberOfSwapChains = 0;
1810 This->d3d_initialized = FALSE;
1814 static void WINAPI IWineD3DDeviceImpl_SetFullscreen(IWineD3DDevice *iface, BOOL fullscreen) {
1815 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
1816 TRACE("(%p) Setting DDraw fullscreen mode to %s\n", This, fullscreen ? "true" : "false");
1818 /* Setup the window for fullscreen mode */
1819 if(fullscreen && !This->ddraw_fullscreen) {
1820 IWineD3DDeviceImpl_SetupFullscreenWindow(iface, This->ddraw_window);
1821 } else if(!fullscreen && This->ddraw_fullscreen) {
1822 IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
1825 /* DirectDraw apps can change between fullscreen and windowed mode after device creation with
1826 * IDirectDraw7::SetCooperativeLevel. The GDI surface implementation needs to know this.
1827 * DDraw doesn't necessarily have a swapchain, so we have to store the fullscreen flag
1830 This->ddraw_fullscreen = fullscreen;
1833 static HRESULT WINAPI IWineD3DDeviceImpl_SetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
1835 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1837 const PixelFormatDesc *formatDesc = getFormatDescEntry(pMode->Format);
1840 TRACE("(%p)->(%d,%p) Mode=%dx%dx@%d, %s\n", This, iSwapChain, pMode, pMode->Width, pMode->Height, pMode->RefreshRate, debug_d3dformat(pMode->Format));
1842 /* Resize the screen even without a window:
1843 * The app could have unset it with SetCooperativeLevel, but not called
1844 * RestoreDisplayMode first. Then the release will call RestoreDisplayMode,
1845 * but we don't have any hwnd
1848 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1849 devmode.dmBitsPerPel = formatDesc->bpp * 8;
1850 if(devmode.dmBitsPerPel == 24) devmode.dmBitsPerPel = 32;
1851 devmode.dmPelsWidth = pMode->Width;
1852 devmode.dmPelsHeight = pMode->Height;
1854 devmode.dmDisplayFrequency = pMode->RefreshRate;
1855 if (pMode->RefreshRate != 0) {
1856 devmode.dmFields |= DM_DISPLAYFREQUENCY;
1859 /* Only change the mode if necessary */
1860 if( (This->ddraw_width == pMode->Width) &&
1861 (This->ddraw_height == pMode->Height) &&
1862 (This->ddraw_format == pMode->Format) &&
1863 (pMode->RefreshRate == 0) ) {
1867 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL);
1868 if (ret != DISP_CHANGE_SUCCESSFUL) {
1869 if(devmode.dmDisplayFrequency != 0) {
1870 WARN("ChangeDisplaySettingsExW failed, trying without the refresh rate\n");
1871 devmode.dmFields &= ~DM_DISPLAYFREQUENCY;
1872 devmode.dmDisplayFrequency = 0;
1873 ret = ChangeDisplaySettingsExW(NULL, &devmode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL;
1875 if(ret != DISP_CHANGE_SUCCESSFUL) {
1876 return DDERR_INVALIDMODE;
1880 /* Store the new values */
1881 This->ddraw_width = pMode->Width;
1882 This->ddraw_height = pMode->Height;
1883 This->ddraw_format = pMode->Format;
1885 /* Only do this with a window of course */
1886 if(This->ddraw_window)
1887 MoveWindow(This->ddraw_window, 0, 0, pMode->Width, pMode->Height, TRUE);
1889 /* And finally clip mouse to our screen */
1890 SetRect(&clip_rc, 0, 0, pMode->Width, pMode->Height);
1891 ClipCursor(&clip_rc);
1896 static HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice *iface, IWineD3D **ppD3D) {
1897 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1898 *ppD3D= This->wineD3D;
1899 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1900 IWineD3D_AddRef(*ppD3D);
1904 static UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1905 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBOs (or whatever)
1906 * into the video ram as possible and seeing how many fit
1907 * you can also get the correct initial value from nvidia and ATI's driver via X
1908 * texture memory is video memory + AGP memory
1909 *******************/
1910 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1911 static BOOL showfixmes = TRUE;
1913 FIXME("(%p) : stub, simulating %dMB for now, returning %dMB left\n", This,
1914 (wined3d_settings.emulated_textureram/(1024*1024)),
1915 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1918 TRACE("(%p) : simulating %dMB, returning %dMB left\n", This,
1919 (wined3d_settings.emulated_textureram/(1024*1024)),
1920 ((wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1921 /* return simulated texture memory left */
1922 return (wined3d_settings.emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1930 static HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1931 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1933 /* Update the current state block */
1934 This->updateStateBlock->changed.fvf = TRUE;
1935 This->updateStateBlock->set.fvf = TRUE;
1937 if(This->updateStateBlock->fvf == fvf) {
1938 TRACE("Application is setting the old fvf over, nothing to do\n");
1942 This->updateStateBlock->fvf = fvf;
1943 TRACE("(%p) : FVF Shader FVF set to %x\n", This, fvf);
1944 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
1949 static HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1950 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1951 TRACE("(%p) : GetFVF returning %x\n", This, This->stateBlock->fvf);
1952 *pfvf = This->stateBlock->fvf;
1957 * Get / Set Stream Source
1959 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1960 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1961 IWineD3DVertexBuffer *oldSrc;
1963 if (StreamNumber >= MAX_STREAMS) {
1964 WARN("Stream out of range %d\n", StreamNumber);
1965 return WINED3DERR_INVALIDCALL;
1968 oldSrc = This->stateBlock->streamSource[StreamNumber];
1969 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1971 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1972 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1974 if(oldSrc == pStreamData &&
1975 This->updateStateBlock->streamStride[StreamNumber] == Stride &&
1976 This->updateStateBlock->streamOffset[StreamNumber] == OffsetInBytes) {
1977 TRACE("Application is setting the old values over, nothing to do\n");
1981 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1983 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1984 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1987 /* Handle recording of state blocks */
1988 if (This->isRecordingState) {
1989 TRACE("Recording... not performing anything\n");
1993 /* Need to do a getParent and pass the reffs up */
1994 /* MSDN says ..... When an application no longer holds a references to this interface, the interface will automatically be freed.
1995 which suggests that we shouldn't be ref counting? and do need a _release on the stream source to reset the stream source
1996 so for now, just count internally */
1997 if (pStreamData != NULL) {
1998 IWineD3DVertexBufferImpl *vbImpl = (IWineD3DVertexBufferImpl *) pStreamData;
1999 InterlockedIncrement(&vbImpl->bindCount);
2001 if (oldSrc != NULL) {
2002 InterlockedDecrement(&((IWineD3DVertexBufferImpl *) oldSrc)->bindCount);
2005 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2010 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
2011 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2013 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber,
2014 This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
2016 if (StreamNumber >= MAX_STREAMS) {
2017 WARN("Stream out of range %d\n", StreamNumber);
2018 return WINED3DERR_INVALIDCALL;
2020 *pStream = This->stateBlock->streamSource[StreamNumber];
2021 *pStride = This->stateBlock->streamStride[StreamNumber];
2023 *pOffset = This->stateBlock->streamOffset[StreamNumber];
2026 if (*pStream != NULL) {
2027 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
2032 static HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
2033 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2034 UINT oldFlags = This->updateStateBlock->streamFlags[StreamNumber];
2035 UINT oldFreq = This->updateStateBlock->streamFreq[StreamNumber];
2037 TRACE("(%p) StreamNumber(%d), Divider(%d)\n", This, StreamNumber, Divider);
2038 This->updateStateBlock->streamFlags[StreamNumber] = Divider & (WINED3DSTREAMSOURCE_INSTANCEDATA | WINED3DSTREAMSOURCE_INDEXEDDATA );
2040 This->updateStateBlock->changed.streamFreq[StreamNumber] = TRUE;
2041 This->updateStateBlock->set.streamFreq[StreamNumber] = TRUE;
2042 This->updateStateBlock->streamFreq[StreamNumber] = Divider & 0x7FFFFF;
2044 if(This->updateStateBlock->streamFreq[StreamNumber] != oldFreq ||
2045 This->updateStateBlock->streamFlags[StreamNumber] != oldFlags) {
2046 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2052 static HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
2053 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2055 TRACE("(%p) StreamNumber(%d), Divider(%p)\n", This, StreamNumber, Divider);
2056 *Divider = This->updateStateBlock->streamFreq[StreamNumber] | This->updateStateBlock->streamFlags[StreamNumber];
2058 TRACE("(%p) : returning %d\n", This, *Divider);
2064 * Get / Set & Multiply Transform
2066 static HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE d3dts, CONST WINED3DMATRIX* lpmatrix) {
2067 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2069 /* Most of this routine, comments included copied from ddraw tree initially: */
2070 TRACE("(%p) : Transform State=%s\n", This, debug_d3dtstype(d3dts));
2072 /* Handle recording of state blocks */
2073 if (This->isRecordingState) {
2074 TRACE("Recording... not performing anything\n");
2075 This->updateStateBlock->changed.transform[d3dts] = TRUE;
2076 This->updateStateBlock->set.transform[d3dts] = TRUE;
2077 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(WINED3DMATRIX));
2082 * If the new matrix is the same as the current one,
2083 * we cut off any further processing. this seems to be a reasonable
2084 * optimization because as was noticed, some apps (warcraft3 for example)
2085 * tend towards setting the same matrix repeatedly for some reason.
2087 * From here on we assume that the new matrix is different, wherever it matters.
2089 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(WINED3DMATRIX))) {
2090 TRACE("The app is setting the same matrix over again\n");
2093 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
2097 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
2098 where ViewMat = Camera space, WorldMat = world space.
2100 In OpenGL, camera and world space is combined into GL_MODELVIEW
2101 matrix. The Projection matrix stay projection matrix.
2104 /* Capture the times we can just ignore the change for now */
2105 if (d3dts == WINED3DTS_VIEW) { /* handle the VIEW matrice */
2106 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
2107 /* Handled by the state manager */
2110 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TRANSFORM(d3dts));
2114 static HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, WINED3DMATRIX* pMatrix) {
2115 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2116 TRACE("(%p) : for Transform State %s\n", This, debug_d3dtstype(State));
2117 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(WINED3DMATRIX));
2121 static HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, WINED3DTRANSFORMSTATETYPE State, CONST WINED3DMATRIX* pMatrix) {
2122 WINED3DMATRIX *mat = NULL;
2125 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
2126 * below means it will be recorded in a state block change, but it
2127 * works regardless where it is recorded.
2128 * If this is found to be wrong, change to StateBlock.
2130 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2131 TRACE("(%p) : For state %s\n", This, debug_d3dtstype(State));
2133 if (State < HIGHEST_TRANSFORMSTATE)
2135 mat = &This->updateStateBlock->transforms[State];
2137 FIXME("Unhandled transform state!!\n");
2140 multiply_matrix(&temp, mat, (const WINED3DMATRIX *) pMatrix);
2142 /* Apply change via set transform - will reapply to eg. lights this way */
2143 return IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
2149 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
2150 you can reference any indexes you want as long as that number max are enabled at any
2151 one point in time! Therefore since the indexes can be anything, we need a hashmap of them.
2152 However, this causes stateblock problems. When capturing the state block, I duplicate the hashmap,
2153 but when recording, just build a chain pretty much of commands to be replayed. */
2155 static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
2157 PLIGHTINFOEL *object = NULL;
2158 UINT Hi = LIGHTMAP_HASHFUNC(Index);
2161 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2162 TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This, Index, pLight, Hi);
2164 /* Check the parameter range. Need for speed most wanted sets junk lights which confuse
2168 WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
2169 return WINED3DERR_INVALIDCALL;
2172 switch(pLight->Type) {
2173 case WINED3DLIGHT_POINT:
2174 case WINED3DLIGHT_SPOT:
2175 case WINED3DLIGHT_PARALLELPOINT:
2176 case WINED3DLIGHT_GLSPOT:
2177 /* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
2180 if(pLight->Attenuation0 < 0.0 || pLight->Attenuation1 < 0.0 || pLight->Attenuation2 < 0.0) {
2181 WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
2182 return WINED3DERR_INVALIDCALL;
2186 case WINED3DLIGHT_DIRECTIONAL:
2187 /* Ignores attenuation */
2191 WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
2192 return WINED3DERR_INVALIDCALL;
2195 LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2196 object = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2197 if(object->OriginalIndex == Index) break;
2202 TRACE("Adding new light\n");
2203 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
2205 ERR("Out of memory error when allocating a light\n");
2206 return E_OUTOFMEMORY;
2208 list_add_head(&This->updateStateBlock->lightMap[Hi], &object->entry);
2209 object->glIndex = -1;
2210 object->OriginalIndex = Index;
2211 object->changed = TRUE;
2214 /* Initialize the object */
2215 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,
2216 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
2217 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
2218 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
2219 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
2220 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
2221 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
2223 /* Save away the information */
2224 memcpy(&object->OriginalParms, pLight, sizeof(WINED3DLIGHT));
2226 switch (pLight->Type) {
2227 case WINED3DLIGHT_POINT:
2229 object->lightPosn[0] = pLight->Position.x;
2230 object->lightPosn[1] = pLight->Position.y;
2231 object->lightPosn[2] = pLight->Position.z;
2232 object->lightPosn[3] = 1.0f;
2233 object->cutoff = 180.0f;
2237 case WINED3DLIGHT_DIRECTIONAL:
2239 object->lightPosn[0] = -pLight->Direction.x;
2240 object->lightPosn[1] = -pLight->Direction.y;
2241 object->lightPosn[2] = -pLight->Direction.z;
2242 object->lightPosn[3] = 0.0;
2243 object->exponent = 0.0f;
2244 object->cutoff = 180.0f;
2247 case WINED3DLIGHT_SPOT:
2249 object->lightPosn[0] = pLight->Position.x;
2250 object->lightPosn[1] = pLight->Position.y;
2251 object->lightPosn[2] = pLight->Position.z;
2252 object->lightPosn[3] = 1.0;
2255 object->lightDirn[0] = pLight->Direction.x;
2256 object->lightDirn[1] = pLight->Direction.y;
2257 object->lightDirn[2] = pLight->Direction.z;
2258 object->lightDirn[3] = 1.0;
2261 * opengl-ish and d3d-ish spot lights use too different models for the
2262 * light "intensity" as a function of the angle towards the main light direction,
2263 * so we only can approximate very roughly.
2264 * however spot lights are rather rarely used in games (if ever used at all).
2265 * furthermore if still used, probably nobody pays attention to such details.
2267 if (pLight->Falloff == 0) {
2270 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
2272 if (rho < 0.0001) rho = 0.0001f;
2273 object->exponent = -0.3/log(cos(rho/2));
2274 if (object->exponent > 128.0) {
2275 object->exponent = 128.0;
2277 object->cutoff = pLight->Phi*90/M_PI;
2283 FIXME("Unrecognized light type %d\n", pLight->Type);
2286 /* Update the live definitions if the light is currently assigned a glIndex */
2287 if (object->glIndex != -1 && !This->isRecordingState) {
2288 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(object->glIndex));
2293 static HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
2294 PLIGHTINFOEL *lightInfo = NULL;
2295 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2296 DWORD Hi = LIGHTMAP_HASHFUNC(Index);
2298 TRACE("(%p) : Idx(%d), pLight(%p)\n", This, Index, pLight);
2300 LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2301 lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2302 if(lightInfo->OriginalIndex == Index) break;
2306 if (lightInfo == NULL) {
2307 TRACE("Light information requested but light not defined\n");
2308 return WINED3DERR_INVALIDCALL;
2311 memcpy(pLight, &lightInfo->OriginalParms, sizeof(WINED3DLIGHT));
2316 * Get / Set Light Enable
2317 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
2319 static HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
2320 PLIGHTINFOEL *lightInfo = NULL;
2321 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2322 UINT Hi = LIGHTMAP_HASHFUNC(Index);
2324 TRACE("(%p) : Idx(%d), enable? %d\n", This, Index, Enable);
2326 /* Tests show true = 128...not clear why */
2327 Enable = Enable? 128: 0;
2329 LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2330 lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2331 if(lightInfo->OriginalIndex == Index) break;
2334 TRACE("Found light: %p\n", lightInfo);
2336 /* Special case - enabling an undefined light creates one with a strict set of parms! */
2337 if (lightInfo == NULL) {
2339 TRACE("Light enabled requested but light not defined, so defining one!\n");
2340 IWineD3DDeviceImpl_SetLight(iface, Index, &WINED3D_default_light);
2342 /* Search for it again! Should be fairly quick as near head of list */
2343 LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
2344 lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2345 if(lightInfo->OriginalIndex == Index) break;
2348 if (lightInfo == NULL) {
2349 FIXME("Adding default lights has failed dismally\n");
2350 return WINED3DERR_INVALIDCALL;
2354 lightInfo->enabledChanged = TRUE;
2356 if(lightInfo->glIndex != -1) {
2357 if(!This->isRecordingState) {
2358 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(lightInfo->glIndex));
2361 This->stateBlock->activeLights[lightInfo->glIndex] = NULL;
2362 lightInfo->glIndex = -1;
2364 TRACE("Light already disabled, nothing to do\n");
2367 if (lightInfo->glIndex != -1) {
2369 TRACE("Nothing to do as light was enabled\n");
2372 /* Find a free gl light */
2373 for(i = 0; i < This->maxConcurrentLights; i++) {
2374 if(This->stateBlock->activeLights[i] == NULL) {
2375 This->stateBlock->activeLights[i] = lightInfo;
2376 lightInfo->glIndex = i;
2380 if(lightInfo->glIndex == -1) {
2381 ERR("Too many concurrently active lights\n");
2382 return WINED3DERR_INVALIDCALL;
2385 /* i == lightInfo->glIndex */
2386 if(!This->isRecordingState) {
2387 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_ACTIVELIGHT(i));
2395 static HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2397 PLIGHTINFOEL *lightInfo = NULL;
2398 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2400 UINT Hi = LIGHTMAP_HASHFUNC(Index);
2401 TRACE("(%p) : for idx(%d)\n", This, Index);
2403 LIST_FOR_EACH(e, &This->stateBlock->lightMap[Hi]) {
2404 lightInfo = LIST_ENTRY(e, PLIGHTINFOEL, entry);
2405 if(lightInfo->OriginalIndex == Index) break;
2409 if (lightInfo == NULL) {
2410 TRACE("Light enabled state requested but light not defined\n");
2411 return WINED3DERR_INVALIDCALL;
2413 /* true is 128 according to SetLightEnable */
2414 *pEnable = lightInfo->glIndex != -1 ? 128 : 0;
2419 * Get / Set Clip Planes
2421 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2422 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2423 TRACE("(%p) : for idx %d, %p\n", This, Index, pPlane);
2425 /* Validate Index */
2426 if (Index >= GL_LIMITS(clipplanes)) {
2427 TRACE("Application has requested clipplane this device doesn't support\n");
2428 return WINED3DERR_INVALIDCALL;
2431 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2432 This->updateStateBlock->set.clipplane[Index] = TRUE;
2434 if(This->updateStateBlock->clipplane[Index][0] == pPlane[0] &&
2435 This->updateStateBlock->clipplane[Index][1] == pPlane[1] &&
2436 This->updateStateBlock->clipplane[Index][2] == pPlane[2] &&
2437 This->updateStateBlock->clipplane[Index][3] == pPlane[3]) {
2438 TRACE("Application is setting old values over, nothing to do\n");
2442 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2443 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2444 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2445 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2447 /* Handle recording of state blocks */
2448 if (This->isRecordingState) {
2449 TRACE("Recording... not performing anything\n");
2453 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_CLIPPLANE(Index));
2458 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2459 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2460 TRACE("(%p) : for idx %d\n", This, Index);
2462 /* Validate Index */
2463 if (Index >= GL_LIMITS(clipplanes)) {
2464 TRACE("Application has requested clipplane this device doesn't support\n");
2465 return WINED3DERR_INVALIDCALL;
2468 pPlane[0] = This->stateBlock->clipplane[Index][0];
2469 pPlane[1] = This->stateBlock->clipplane[Index][1];
2470 pPlane[2] = This->stateBlock->clipplane[Index][2];
2471 pPlane[3] = This->stateBlock->clipplane[Index][3];
2476 * Get / Set Clip Plane Status
2477 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2479 static HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2480 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2481 FIXME("(%p) : stub\n", This);
2482 if (NULL == pClipStatus) {
2483 return WINED3DERR_INVALIDCALL;
2485 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2486 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2490 static HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2491 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2492 FIXME("(%p) : stub\n", This);
2493 if (NULL == pClipStatus) {
2494 return WINED3DERR_INVALIDCALL;
2496 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2497 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2502 * Get / Set Material
2504 static HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2505 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2507 This->updateStateBlock->changed.material = TRUE;
2508 This->updateStateBlock->set.material = TRUE;
2509 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2511 /* Handle recording of state blocks */
2512 if (This->isRecordingState) {
2513 TRACE("Recording... not performing anything\n");
2518 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2519 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2520 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2521 pMaterial->Ambient.b, pMaterial->Ambient.a);
2522 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2523 pMaterial->Specular.b, pMaterial->Specular.a);
2524 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2525 pMaterial->Emissive.b, pMaterial->Emissive.a);
2526 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2528 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2529 checkGLcall("glMaterialfv(GL_AMBIENT)");
2530 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2531 checkGLcall("glMaterialfv(GL_DIFFUSE)");
2533 /* Only change material color if specular is enabled, otherwise it is set to black */
2534 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2535 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2536 checkGLcall("glMaterialfv(GL_SPECULAR");
2538 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2539 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2540 checkGLcall("glMaterialfv(GL_SPECULAR");
2542 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2543 checkGLcall("glMaterialfv(GL_EMISSION)");
2544 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2545 checkGLcall("glMaterialf(GL_SHININESS");
2551 static HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2552 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2553 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2554 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g,
2555 pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2556 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g,
2557 pMaterial->Ambient.b, pMaterial->Ambient.a);
2558 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g,
2559 pMaterial->Specular.b, pMaterial->Specular.a);
2560 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g,
2561 pMaterial->Emissive.b, pMaterial->Emissive.a);
2562 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2570 static HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2571 UINT BaseVertexIndex) {
2572 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2573 IWineD3DIndexBuffer *oldIdxs;
2574 UINT oldBaseIndex = This->updateStateBlock->baseVertexIndex;
2576 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2577 oldIdxs = This->updateStateBlock->pIndexData;
2579 This->updateStateBlock->changed.indices = TRUE;
2580 This->updateStateBlock->set.indices = TRUE;
2581 This->updateStateBlock->pIndexData = pIndexData;
2582 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2584 /* Handle recording of state blocks */
2585 if (This->isRecordingState) {
2586 TRACE("Recording... not performing anything\n");
2590 /* The base vertex index affects the stream sources, while
2591 * The index buffer is a seperate index buffer state
2593 if(BaseVertexIndex != oldBaseIndex) {
2594 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2596 if(oldIdxs != pIndexData) {
2597 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
2602 static HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2603 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2605 *ppIndexData = This->stateBlock->pIndexData;
2607 /* up ref count on ppindexdata */
2609 IWineD3DIndexBuffer_AddRef(*ppIndexData);
2610 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2611 TRACE("(%p) index data set to %p + %u\n", This, ppIndexData, This->stateBlock->baseVertexIndex);
2613 TRACE("(%p) No index data set\n", This);
2615 TRACE("Returning %p %d\n", *ppIndexData, *pBaseVertexIndex);
2620 /* Method to offer d3d9 a simple way to set the base vertex index without messing with the index buffer */
2621 static HRESULT WINAPI IWineD3DDeviceImpl_SetBasevertexIndex(IWineD3DDevice *iface, UINT BaseIndex) {
2622 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2623 TRACE("(%p)->(%d)\n", This, BaseIndex);
2625 if(This->updateStateBlock->baseVertexIndex == BaseIndex) {
2626 TRACE("Application is setting the old value over, nothing to do\n");
2630 This->updateStateBlock->baseVertexIndex = BaseIndex;
2632 if (This->isRecordingState) {
2633 TRACE("Recording... not performing anything\n");
2636 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
2641 * Get / Set Viewports
2643 static HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2644 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2646 TRACE("(%p)\n", This);
2647 This->updateStateBlock->changed.viewport = TRUE;
2648 This->updateStateBlock->set.viewport = TRUE;
2649 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2651 /* Handle recording of state blocks */
2652 if (This->isRecordingState) {
2653 TRACE("Recording... not performing anything\n");
2657 TRACE("(%p) : x=%d, y=%d, wid=%d, hei=%d, minz=%f, maxz=%f\n", This,
2658 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2660 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
2665 static HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2666 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2667 TRACE("(%p)\n", This);
2668 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2673 * Get / Set Render States
2674 * TODO: Verify against dx9 definitions
2676 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD Value) {
2678 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2679 DWORD oldValue = This->stateBlock->renderState[State];
2681 TRACE("(%p)->state = %s(%d), value = %d\n", This, debug_d3drenderstate(State), State, Value);
2683 This->updateStateBlock->changed.renderState[State] = TRUE;
2684 This->updateStateBlock->set.renderState[State] = TRUE;
2685 This->updateStateBlock->renderState[State] = Value;
2687 /* Handle recording of state blocks */
2688 if (This->isRecordingState) {
2689 TRACE("Recording... not performing anything\n");
2693 /* Compared here and not before the assignment to allow proper stateblock recording */
2694 if(Value == oldValue) {
2695 TRACE("Application is setting the old value over, nothing to do\n");
2697 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(State));
2703 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, WINED3DRENDERSTATETYPE State, DWORD *pValue) {
2704 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2705 TRACE("(%p) for State %d = %d\n", This, State, This->stateBlock->renderState[State]);
2706 *pValue = This->stateBlock->renderState[State];
2711 * Get / Set Sampler States
2712 * TODO: Verify against dx9 definitions
2715 static HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
2716 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2717 DWORD oldValue = This->stateBlock->samplerState[Sampler][Type];
2720 * SetSampler is designed to allow for more than the standard up to 8 textures
2721 * and Geforce has stopped supporting more than 6 standard textures in openGL.
2722 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
2724 * http://developer.nvidia.com/object/General_FAQ.html#t6
2726 * There are two new settings for GForce
2728 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
2729 * and the texture one:
2730 * GL_MAX_TEXTURE_COORDS_ARB.
2731 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
2734 TRACE("(%p) : Sampler=%d, Type=%s(%d), Value=%d\n", This, Sampler,
2735 debug_d3dsamplerstate(Type), Type, Value);
2736 This->updateStateBlock->samplerState[Sampler][Type] = Value;
2737 This->updateStateBlock->set.samplerState[Sampler][Type] = Value;
2738 This->updateStateBlock->changed.samplerState[Sampler][Type] = Value;
2740 /* Handle recording of state blocks */
2741 if (This->isRecordingState) {
2742 TRACE("Recording... not performing anything\n");
2746 if(oldValue == Value) {
2747 TRACE("Application is setting the old value over, nothing to do\n");
2751 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Sampler));
2756 static HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
2757 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2758 *Value = This->stateBlock->samplerState[Sampler][Type];
2759 TRACE("(%p) : Sampler %d Type %u Returning %d\n", This, Sampler, Type, *Value);
2764 static HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
2765 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2767 This->updateStateBlock->set.scissorRect = TRUE;
2768 This->updateStateBlock->changed.scissorRect = TRUE;
2769 if(EqualRect(&This->updateStateBlock->scissorRect, pRect)) {
2770 TRACE("App is setting the old scissor rectangle over, nothing to do\n");
2773 CopyRect(&This->updateStateBlock->scissorRect, pRect);
2775 if(This->isRecordingState) {
2776 TRACE("Recording... not performing anything\n");
2780 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SCISSORRECT);
2785 static HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
2786 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2788 memcpy(pRect, &This->updateStateBlock->scissorRect, sizeof(pRect));
2789 TRACE("(%p)Returning a Scissor Rect of %d:%d-%d:%d\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
2793 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
2794 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
2795 IWineD3DVertexDeclaration *oldDecl = This->updateStateBlock->vertexDecl;
2797 TRACE("(%p) : pDecl=%p\n", This, pDecl);
2799 This->updateStateBlock->vertexDecl = pDecl;
2800 This->updateStateBlock->changed.vertexDecl = TRUE;
2801 This->updateStateBlock->set.vertexDecl = TRUE;
2803 if (This->isRecordingState) {
2804 TRACE("Recording... not performing anything\n");
2806 } else if(pDecl == oldDecl) {
2807 /* Checked after the assignment to allow proper stateblock recording */
2808 TRACE("Application is setting the old declaration over, nothing to do\n");
2812 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
2816 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
2817 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2819 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
2821 *ppDecl = This->stateBlock->vertexDecl;
2822 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
2826 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
2827 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2828 IWineD3DVertexShader* oldShader = This->updateStateBlock->vertexShader;
2830 This->updateStateBlock->vertexShader = pShader;
2831 This->updateStateBlock->changed.vertexShader = TRUE;
2832 This->updateStateBlock->set.vertexShader = TRUE;
2834 if (This->isRecordingState) {
2835 TRACE("Recording... not performing anything\n");
2837 } else if(oldShader == pShader) {
2838 /* Checked here to allow proper stateblock recording */
2839 TRACE("App is setting the old shader over, nothing to do\n");
2843 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
2845 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VSHADER);
2850 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
2851 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2853 if (NULL == ppShader) {
2854 return WINED3DERR_INVALIDCALL;
2856 *ppShader = This->stateBlock->vertexShader;
2857 if( NULL != *ppShader)
2858 IWineD3DVertexShader_AddRef(*ppShader);
2860 TRACE("(%p) : returning %p\n", This, *ppShader);
2864 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(
2865 IWineD3DDevice *iface,
2867 CONST BOOL *srcData,
2870 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2871 int i, cnt = min(count, MAX_CONST_B - start);
2873 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2874 iface, srcData, start, count);
2876 if (srcData == NULL || cnt < 0)
2877 return WINED3DERR_INVALIDCALL;
2879 memcpy(&This->updateStateBlock->vertexShaderConstantB[start], srcData, cnt * sizeof(BOOL));
2880 for (i = 0; i < cnt; i++)
2881 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
2883 for (i = start; i < cnt + start; ++i) {
2884 This->updateStateBlock->changed.vertexShaderConstantsB[i] = TRUE;
2885 This->updateStateBlock->set.vertexShaderConstantsB[i] = TRUE;
2888 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
2893 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(
2894 IWineD3DDevice *iface,
2899 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2900 int cnt = min(count, MAX_CONST_B - start);
2902 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2903 iface, dstData, start, count);
2905 if (dstData == NULL || cnt < 0)
2906 return WINED3DERR_INVALIDCALL;
2908 memcpy(dstData, &This->stateBlock->vertexShaderConstantB[start], cnt * sizeof(BOOL));
2912 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(
2913 IWineD3DDevice *iface,
2918 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2919 int i, cnt = min(count, MAX_CONST_I - start);
2921 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2922 iface, srcData, start, count);
2924 if (srcData == NULL || cnt < 0)
2925 return WINED3DERR_INVALIDCALL;
2927 memcpy(&This->updateStateBlock->vertexShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
2928 for (i = 0; i < cnt; i++)
2929 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
2930 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
2932 for (i = start; i < cnt + start; ++i) {
2933 This->updateStateBlock->changed.vertexShaderConstantsI[i] = TRUE;
2934 This->updateStateBlock->set.vertexShaderConstantsI[i] = TRUE;
2937 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
2942 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(
2943 IWineD3DDevice *iface,
2948 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2949 int cnt = min(count, MAX_CONST_I - start);
2951 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
2952 iface, dstData, start, count);
2954 if (dstData == NULL || ((signed int) MAX_CONST_I - (signed int) start) <= (signed int) 0)
2955 return WINED3DERR_INVALIDCALL;
2957 memcpy(dstData, &This->stateBlock->vertexShaderConstantI[start * 4], cnt * sizeof(int) * 4);
2961 static HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(
2962 IWineD3DDevice *iface,
2964 CONST float *srcData,
2967 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2970 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
2971 iface, srcData, start, count);
2973 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
2974 if (srcData == NULL || start + count > GL_LIMITS(vshader_constantsF) || start > GL_LIMITS(vshader_constantsF))
2975 return WINED3DERR_INVALIDCALL;
2977 memcpy(&This->updateStateBlock->vertexShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
2979 for (i = 0; i < count; i++)
2980 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
2981 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
2984 for (i = start; i < count + start; ++i) {
2985 if (!This->updateStateBlock->set.vertexShaderConstantsF[i]) {
2986 constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_vconstantsF), constants_entry, entry);
2987 if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
2988 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
2989 list_add_head(&This->updateStateBlock->set_vconstantsF, &ptr->entry);
2991 ptr->idx[ptr->count++] = i;
2992 This->updateStateBlock->set.vertexShaderConstantsF[i] = TRUE;
2994 This->updateStateBlock->changed.vertexShaderConstantsF[i] = TRUE;
2997 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VERTEXSHADERCONSTANT);
3002 static HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(
3003 IWineD3DDevice *iface,
3008 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3009 int cnt = min(count, GL_LIMITS(vshader_constantsF) - start);
3011 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3012 iface, dstData, start, count);
3014 if (dstData == NULL || cnt < 0)
3015 return WINED3DERR_INVALIDCALL;
3017 memcpy(dstData, &This->stateBlock->vertexShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3021 static inline void markTextureStagesDirty(IWineD3DDeviceImpl *This, DWORD stage) {
3023 for(i = 0; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
3024 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(stage, i));
3028 static void IWineD3DDeviceImpl_FindTexUnitMap(IWineD3DDeviceImpl *This) {
3030 /* This code can assume that GL_NV_register_combiners are supported, otherwise
3031 * it is never called.
3034 * -> Pixel shaders need a 1:1 map. In theory the shader input could be mapped too, but
3035 * that would be really messy and require shader recompilation
3036 * -> When the mapping of a stage is changed, sampler and ALL texture stage states have
3037 * to be reset. Because of that try to work with a 1:1 mapping as much as possible
3038 * -> Whith a 1:1 mapping oneToOneTexUnitMap is set to avoid checking MAX_SAMPLERS array
3039 * entries to make pixel shaders cheaper. MAX_SAMPLERS will be 128 in dx10
3041 if(This->stateBlock->pixelShader || This->stateBlock->lowest_disabled_stage <= GL_LIMITS(textures)) {
3042 if(This->oneToOneTexUnitMap) {
3043 TRACE("Not touching 1:1 map\n");
3046 TRACE("Restoring 1:1 texture unit mapping\n");
3047 /* Restore a 1:1 mapping */
3048 for(i = 0; i < MAX_SAMPLERS; i++) {
3049 if(This->texUnitMap[i] != i) {
3050 This->texUnitMap[i] = i;
3051 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3052 markTextureStagesDirty(This, i);
3055 This->oneToOneTexUnitMap = TRUE;
3058 /* No pixel shader, and we do not have enough texture units available. Try to skip NULL textures
3059 * First, see if we can succeed at all
3062 for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3063 if(This->stateBlock->textures[i] == NULL) tex++;
3066 if(GL_LIMITS(textures) + tex < This->stateBlock->lowest_disabled_stage) {
3067 FIXME("Too many bound textures to support the combiner settings\n");
3071 /* Now work out the mapping */
3073 This->oneToOneTexUnitMap = FALSE;
3074 WARN("Non 1:1 mapping UNTESTED!\n");
3075 for(i = 0; i < This->stateBlock->lowest_disabled_stage; i++) {
3076 /* Skip NULL textures */
3077 if (!This->stateBlock->textures[i]) {
3078 /* Map to -1, so the check below doesn't fail if a non-NULL
3079 * texture is set on this stage */
3080 TRACE("Mapping texture stage %d to -1\n", i);
3081 This->texUnitMap[i] = -1;
3086 TRACE("Mapping texture stage %d to unit %d\n", i, tex);
3087 if(This->texUnitMap[i] != tex) {
3088 This->texUnitMap[i] = tex;
3089 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(i));
3090 markTextureStagesDirty(This, i);
3098 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3099 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3100 IWineD3DPixelShader *oldShader = This->updateStateBlock->pixelShader;
3101 This->updateStateBlock->pixelShader = pShader;
3102 This->updateStateBlock->changed.pixelShader = TRUE;
3103 This->updateStateBlock->set.pixelShader = TRUE;
3105 /* Handle recording of state blocks */
3106 if (This->isRecordingState) {
3107 TRACE("Recording... not performing anything\n");
3110 if (This->isRecordingState) {
3111 TRACE("Recording... not performing anything\n");
3115 if(pShader == oldShader) {
3116 TRACE("App is setting the old pixel shader over, nothing to do\n");
3120 TRACE("(%p) : setting pShader(%p)\n", This, pShader);
3121 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADER);
3123 /* Rebuild the texture unit mapping if nvrc's are supported */
3124 if(GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3125 IWineD3DDeviceImpl_FindTexUnitMap(This);
3131 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3132 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3134 if (NULL == ppShader) {
3135 WARN("(%p) : PShader is NULL, returning INVALIDCALL\n", This);
3136 return WINED3DERR_INVALIDCALL;
3139 *ppShader = This->stateBlock->pixelShader;
3140 if (NULL != *ppShader) {
3141 IWineD3DPixelShader_AddRef(*ppShader);
3143 TRACE("(%p) : returning %p\n", This, *ppShader);
3147 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(
3148 IWineD3DDevice *iface,
3150 CONST BOOL *srcData,
3153 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3154 int i, cnt = min(count, MAX_CONST_B - start);
3156 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3157 iface, srcData, start, count);
3159 if (srcData == NULL || cnt < 0)
3160 return WINED3DERR_INVALIDCALL;
3162 memcpy(&This->updateStateBlock->pixelShaderConstantB[start], srcData, cnt * sizeof(BOOL));
3163 for (i = 0; i < cnt; i++)
3164 TRACE("Set BOOL constant %u to %s\n", start + i, srcData[i]? "true":"false");
3166 for (i = start; i < cnt + start; ++i) {
3167 This->updateStateBlock->changed.pixelShaderConstantsB[i] = TRUE;
3168 This->updateStateBlock->set.pixelShaderConstantsB[i] = TRUE;
3171 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3176 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(
3177 IWineD3DDevice *iface,
3182 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3183 int cnt = min(count, MAX_CONST_B - start);
3185 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3186 iface, dstData, start, count);
3188 if (dstData == NULL || cnt < 0)
3189 return WINED3DERR_INVALIDCALL;
3191 memcpy(dstData, &This->stateBlock->pixelShaderConstantB[start], cnt * sizeof(BOOL));
3195 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(
3196 IWineD3DDevice *iface,
3201 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3202 int i, cnt = min(count, MAX_CONST_I - start);
3204 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3205 iface, srcData, start, count);
3207 if (srcData == NULL || cnt < 0)
3208 return WINED3DERR_INVALIDCALL;
3210 memcpy(&This->updateStateBlock->pixelShaderConstantI[start * 4], srcData, cnt * sizeof(int) * 4);
3211 for (i = 0; i < cnt; i++)
3212 TRACE("Set INT constant %u to { %d, %d, %d, %d }\n", start + i,
3213 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3215 for (i = start; i < cnt + start; ++i) {
3216 This->updateStateBlock->changed.pixelShaderConstantsI[i] = TRUE;
3217 This->updateStateBlock->set.pixelShaderConstantsI[i] = TRUE;
3220 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3225 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(
3226 IWineD3DDevice *iface,
3231 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3232 int cnt = min(count, MAX_CONST_I - start);
3234 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3235 iface, dstData, start, count);
3237 if (dstData == NULL || cnt < 0)
3238 return WINED3DERR_INVALIDCALL;
3240 memcpy(dstData, &This->stateBlock->pixelShaderConstantI[start * 4], cnt * sizeof(int) * 4);
3244 static HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(
3245 IWineD3DDevice *iface,
3247 CONST float *srcData,
3250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3253 TRACE("(iface %p, srcData %p, start %d, count %d)\n",
3254 iface, srcData, start, count);
3256 /* Specifically test start > limit to catch MAX_UINT overflows when adding start + count */
3257 if (srcData == NULL || start + count > GL_LIMITS(pshader_constantsF) || start > GL_LIMITS(pshader_constantsF))
3258 return WINED3DERR_INVALIDCALL;
3260 memcpy(&This->updateStateBlock->pixelShaderConstantF[start * 4], srcData, count * sizeof(float) * 4);
3262 for (i = 0; i < count; i++)
3263 TRACE("Set FLOAT constant %u to { %f, %f, %f, %f }\n", start + i,
3264 srcData[i*4], srcData[i*4+1], srcData[i*4+2], srcData[i*4+3]);
3267 for (i = start; i < count + start; ++i) {
3268 if (!This->updateStateBlock->set.pixelShaderConstantsF[i]) {
3269 constants_entry *ptr = LIST_ENTRY(list_head(&This->updateStateBlock->set_pconstantsF), constants_entry, entry);
3270 if (!ptr || ptr->count >= sizeof(ptr->idx) / sizeof(*ptr->idx)) {
3271 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(constants_entry));
3272 list_add_head(&This->updateStateBlock->set_pconstantsF, &ptr->entry);
3274 ptr->idx[ptr->count++] = i;
3275 This->updateStateBlock->set.pixelShaderConstantsF[i] = TRUE;
3277 This->updateStateBlock->changed.pixelShaderConstantsF[i] = TRUE;
3280 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_PIXELSHADERCONSTANT);
3285 static HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(
3286 IWineD3DDevice *iface,
3291 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3292 int cnt = min(count, GL_LIMITS(pshader_constantsF) - start);
3294 TRACE("(iface %p, dstData %p, start %d, count %d)\n",
3295 iface, dstData, start, count);
3297 if (dstData == NULL || cnt < 0)
3298 return WINED3DERR_INVALIDCALL;
3300 memcpy(dstData, &This->stateBlock->pixelShaderConstantF[start * 4], cnt * sizeof(float) * 4);
3304 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
3306 process_vertices_strided(IWineD3DDeviceImpl *This, DWORD dwDestIndex, DWORD dwCount, WineDirect3DVertexStridedData *lpStrideData, DWORD SrcFVF, IWineD3DVertexBufferImpl *dest, DWORD dwFlags) {
3307 char *dest_ptr, *dest_conv = NULL, *dest_conv_addr = NULL;
3309 DWORD DestFVF = dest->fvf;
3311 WINED3DMATRIX mat, proj_mat, view_mat, world_mat;
3315 if (SrcFVF & WINED3DFVF_NORMAL) {
3316 WARN(" lighting state not saved yet... Some strange stuff may happen !\n");
3319 if ( (SrcFVF & WINED3DFVF_POSITION_MASK) != WINED3DFVF_XYZ) {
3320 ERR("Source has no position mask\n");
3321 return WINED3DERR_INVALIDCALL;
3324 /* We might access VBOs from this code, so hold the lock */
3327 if (dest->resource.allocatedMemory == NULL) {
3328 /* This may happen if we do direct locking into a vbo. Unlikely,
3329 * but theoretically possible(ddraw processvertices test)
3331 dest->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, dest->resource.size);
3332 if(!dest->resource.allocatedMemory) {
3334 ERR("Out of memory\n");
3335 return E_OUTOFMEMORY;
3339 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3340 checkGLcall("glBindBufferARB");
3341 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3343 memcpy(dest->resource.allocatedMemory, src, dest->resource.size);
3345 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3346 checkGLcall("glUnmapBufferARB");
3350 /* Get a pointer into the destination vbo(create one if none exists) and
3351 * write correct opengl data into it. It's cheap and allows us to run drawStridedFast
3353 if(!dest->vbo && GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3358 dest_conv_addr = HeapAlloc(GetProcessHeap(), 0, dwCount * get_flexible_vertex_size(DestFVF));
3359 if(!dest_conv_addr) {
3360 ERR("Out of memory\n");
3361 /* Continue without storing converted vertices */
3363 dest_conv = dest_conv_addr;
3367 * a) WINED3DRS_CLIPPING is enabled
3368 * b) WINED3DVOP_CLIP is passed
3370 if(This->stateBlock->renderState[WINED3DRS_CLIPPING]) {
3371 static BOOL warned = FALSE;
3373 * The clipping code is not quite correct. Some things need
3374 * to be checked against IDirect3DDevice3 (!), d3d8 and d3d9,
3375 * so disable clipping for now.
3376 * (The graphics in Half-Life are broken, and my processvertices
3377 * test crashes with IDirect3DDevice3)
3383 FIXME("Clipping is broken and disabled for now\n");
3385 } else doClip = FALSE;
3386 dest_ptr = ((char *) dest->resource.allocatedMemory) + dwDestIndex * get_flexible_vertex_size(DestFVF);
3388 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3391 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3392 WINED3DTS_PROJECTION,
3394 IWineD3DDevice_GetTransform( (IWineD3DDevice *) This,
3395 WINED3DTS_WORLDMATRIX(0),
3398 TRACE("View mat:\n");
3399 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);
3400 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);
3401 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);
3402 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);
3404 TRACE("Proj mat:\n");
3405 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);
3406 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);
3407 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);
3408 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);
3410 TRACE("World mat:\n");
3411 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);
3412 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);
3413 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);
3414 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);
3416 /* Get the viewport */
3417 IWineD3DDevice_GetViewport( (IWineD3DDevice *) This, &vp);
3418 TRACE("Viewport: X=%d, Y=%d, Width=%d, Height=%d, MinZ=%f, MaxZ=%f\n",
3419 vp.X, vp.Y, vp.Width, vp.Height, vp.MinZ, vp.MaxZ);
3421 multiply_matrix(&mat,&view_mat,&world_mat);
3422 multiply_matrix(&mat,&proj_mat,&mat);
3424 numTextures = (DestFVF & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
3426 for (i = 0; i < dwCount; i+= 1) {
3427 unsigned int tex_index;
3429 if ( ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
3430 ((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
3431 /* The position first */
3433 (float *) (((char *) lpStrideData->u.s.position.lpData) + i * lpStrideData->u.s.position.dwStride);
3435 TRACE("In: ( %06.2f %06.2f %06.2f )\n", p[0], p[1], p[2]);
3437 /* Multiplication with world, view and projection matrix */
3438 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);
3439 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);
3440 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);
3441 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);
3443 TRACE("x=%f y=%f z=%f rhw=%f\n", x, y, z, rhw);
3445 /* WARNING: The following things are taken from d3d7 and were not yet checked
3446 * against d3d8 or d3d9!
3449 /* Clipping conditions: From
3450 * http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/fixedfunction/viewportsclipping/clippingvolumes.asp
3452 * A vertex is clipped if it does not match the following requirements
3456 * 0 < rhw ( Not in d3d7, but tested in d3d7)
3458 * If clipping is on is determined by the D3DVOP_CLIP flag in D3D7, and
3459 * by the D3DRS_CLIPPING in D3D9(according to the msdn, not checked)
3464 ( (-rhw -eps < x) && (-rhw -eps < y) && ( -eps < z) &&
3465 (x <= rhw + eps) && (y <= rhw + eps ) && (z <= rhw + eps) &&
3468 /* "Normal" viewport transformation (not clipped)
3469 * 1) The values are divided by rhw
3470 * 2) The y axis is negative, so multiply it with -1
3471 * 3) Screen coordinates go from -(Width/2) to +(Width/2) and
3472 * -(Height/2) to +(Height/2). The z range is MinZ to MaxZ
3473 * 4) Multiply x with Width/2 and add Width/2
3474 * 5) The same for the height
3475 * 6) Add the viewpoint X and Y to the 2D coordinates and
3476 * The minimum Z value to z
3477 * 7) rhw = 1 / rhw Reciprocal of Homogeneous W....
3479 * Well, basically it's simply a linear transformation into viewport
3491 z *= vp.MaxZ - vp.MinZ;
3493 x += vp.Width / 2 + vp.X;
3494 y += vp.Height / 2 + vp.Y;
3499 /* That vertex got clipped
3500 * Contrary to OpenGL it is not dropped completely, it just
3501 * undergoes a different calculation.
3503 TRACE("Vertex got clipped\n");
3510 /* Msdn mentions that Direct3D9 keeps a list of clipped vertices
3511 * outside of the main vertex buffer memory. That needs some more
3516 TRACE("Writing (%f %f %f) %f\n", x, y, z, rhw);
3519 ( (float *) dest_ptr)[0] = x;
3520 ( (float *) dest_ptr)[1] = y;
3521 ( (float *) dest_ptr)[2] = z;
3522 ( (float *) dest_ptr)[3] = rhw; /* SIC, see ddraw test! */
3524 dest_ptr += 3 * sizeof(float);
3526 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3527 dest_ptr += sizeof(float);
3532 ( (float *) dest_conv)[0] = x * w;
3533 ( (float *) dest_conv)[1] = y * w;
3534 ( (float *) dest_conv)[2] = z * w;
3535 ( (float *) dest_conv)[3] = w;
3537 dest_conv += 3 * sizeof(float);
3539 if((DestFVF & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW) {
3540 dest_conv += sizeof(float);
3544 if (DestFVF & WINED3DFVF_PSIZE) {
3545 dest_ptr += sizeof(DWORD);
3546 if(dest_conv) dest_conv += sizeof(DWORD);
3548 if (DestFVF & WINED3DFVF_NORMAL) {
3550 (float *) (((float *) lpStrideData->u.s.normal.lpData) + i * lpStrideData->u.s.normal.dwStride);
3551 /* AFAIK this should go into the lighting information */
3552 FIXME("Didn't expect the destination to have a normal\n");
3553 copy_and_next(dest_ptr, normal, 3 * sizeof(float));
3555 copy_and_next(dest_conv, normal, 3 * sizeof(float));
3559 if (DestFVF & WINED3DFVF_DIFFUSE) {
3561 (DWORD *) (((char *) lpStrideData->u.s.diffuse.lpData) + i * lpStrideData->u.s.diffuse.dwStride);
3563 static BOOL warned = FALSE;
3566 ERR("No diffuse color in source, but destination has one\n");
3570 *( (DWORD *) dest_ptr) = 0xffffffff;
3571 dest_ptr += sizeof(DWORD);
3574 *( (DWORD *) dest_conv) = 0xffffffff;
3575 dest_conv += sizeof(DWORD);
3579 copy_and_next(dest_ptr, color_d, sizeof(DWORD));
3581 *( (DWORD *) dest_conv) = (*color_d & 0xff00ff00) ; /* Alpha + green */
3582 *( (DWORD *) dest_conv) |= (*color_d & 0x00ff0000) >> 16; /* Red */
3583 *( (DWORD *) dest_conv) |= (*color_d & 0xff0000ff) << 16; /* Blue */
3584 dest_conv += sizeof(DWORD);
3589 if (DestFVF & WINED3DFVF_SPECULAR) {
3590 /* What's the color value in the feedback buffer? */
3592 (DWORD *) (((char *) lpStrideData->u.s.specular.lpData) + i * lpStrideData->u.s.specular.dwStride);
3594 static BOOL warned = FALSE;
3597 ERR("No specular color in source, but destination has one\n");
3601 *( (DWORD *) dest_ptr) = 0xFF000000;
3602 dest_ptr += sizeof(DWORD);
3605 *( (DWORD *) dest_conv) = 0xFF000000;
3606 dest_conv += sizeof(DWORD);
3610 copy_and_next(dest_ptr, color_s, sizeof(DWORD));
3612 *( (DWORD *) dest_conv) = (*color_s & 0xff00ff00) ; /* Alpha + green */
3613 *( (DWORD *) dest_conv) |= (*color_s & 0x00ff0000) >> 16; /* Red */
3614 *( (DWORD *) dest_conv) |= (*color_s & 0xff0000ff) << 16; /* Blue */
3615 dest_conv += sizeof(DWORD);
3620 for (tex_index = 0; tex_index < numTextures; tex_index++) {
3622 (float *) (((char *) lpStrideData->u.s.texCoords[tex_index].lpData) +
3623 i * lpStrideData->u.s.texCoords[tex_index].dwStride);
3625 ERR("No source texture, but destination requests one\n");
3626 dest_ptr+=GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3627 if(dest_conv) dest_conv += GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float);
3630 copy_and_next(dest_ptr, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3632 copy_and_next(dest_conv, tex_coord, GET_TEXCOORD_SIZE_FROM_FVF(DestFVF, tex_index) * sizeof(float));
3639 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, dest->vbo));
3640 checkGLcall("glBindBufferARB(GL_ARRAY_BUFFER_ARB)");
3641 GL_EXTCALL(glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, dwDestIndex * get_flexible_vertex_size(DestFVF),
3642 dwCount * get_flexible_vertex_size(DestFVF),
3644 checkGLcall("glBufferSubDataARB(GL_ARRAY_BUFFER_ARB)");
3645 HeapFree(GetProcessHeap(), 0, dest_conv_addr);
3652 #undef copy_and_next
3654 static HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3656 IWineD3DVertexBufferImpl *SrcImpl = (IWineD3DVertexBufferImpl *) pVertexDecl;
3657 WineDirect3DVertexStridedData strided;
3658 TRACE("(%p)->(%d,%d,%d,%p,%p,%d\n", This, SrcStartIndex, DestIndex, VertexCount, pDestBuffer, pVertexDecl, Flags);
3661 WARN("NULL source vertex buffer\n");
3662 return WINED3DERR_INVALIDCALL;
3664 /* We don't need the source vbo because this buffer is only used as
3665 * a source for ProcessVertices. Avoid wasting resources by converting the
3666 * buffer and loading the VBO
3669 TRACE("Releasing the source vbo, it won't be needed\n");
3671 if(!SrcImpl->resource.allocatedMemory) {
3672 /* Rescue the data from the buffer */
3674 SrcImpl->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), 0, SrcImpl->resource.size);
3675 if(!SrcImpl->resource.allocatedMemory) {
3676 ERR("Out of memory\n");
3677 return E_OUTOFMEMORY;
3681 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, SrcImpl->vbo));
3682 checkGLcall("glBindBufferARB");
3684 src = GL_EXTCALL(glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB));
3686 memcpy(SrcImpl->resource.allocatedMemory, src, SrcImpl->resource.size);
3689 GL_EXTCALL(glUnmapBufferARB(GL_ARRAY_BUFFER_ARB));
3690 checkGLcall("glUnmapBufferARB");
3695 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
3696 checkGLcall("glBindBufferARB");
3697 GL_EXTCALL(glDeleteBuffersARB(1, &SrcImpl->vbo));
3698 checkGLcall("glDeleteBuffersARB");
3704 memset(&strided, 0, sizeof(strided));
3705 primitiveConvertFVFtoOffset(SrcImpl->fvf, get_flexible_vertex_size(SrcImpl->fvf), SrcImpl->resource.allocatedMemory + get_flexible_vertex_size(SrcImpl->fvf) * SrcStartIndex, &strided, 0, 0);
3707 return process_vertices_strided(This, DestIndex, VertexCount, &strided, SrcImpl->fvf, (IWineD3DVertexBufferImpl *) pDestBuffer, Flags);
3711 * Get / Set Texture Stage States
3712 * TODO: Verify against dx9 definitions
3714 static HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3715 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3716 DWORD oldValue = This->updateStateBlock->textureState[Stage][Type];
3718 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3720 TRACE("(%p) : Stage=%d, Type=%s(%d), Value=%d\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3722 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3723 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3724 This->updateStateBlock->textureState[Stage][Type] = Value;
3726 if (This->isRecordingState) {
3727 TRACE("Recording... not performing anything\n");
3731 /* Checked after the assignments to allow proper stateblock recording */
3732 if(oldValue == Value) {
3733 TRACE("App is setting the old value over, nothing to do\n");
3737 if(Stage > This->stateBlock->lowest_disabled_stage &&
3738 StateTable[STATE_TEXTURESTAGE(0, Type)].representative == STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP)) {
3739 /* Colorop change above lowest disabled stage? That won't change anything in the gl setup
3740 * Changes in other states are important on disabled stages too
3745 if(Type == WINED3DTSS_COLOROP) {
3748 if(Value == WINED3DTOP_DISABLE && oldValue != WINED3DTOP_DISABLE) {
3749 /* Previously enabled stage disabled now. Make sure to dirtify all enabled stages above Stage,
3750 * they have to be disabled
3752 * The current stage is dirtified below.
3754 for(i = Stage + 1; i < This->stateBlock->lowest_disabled_stage; i++) {
3755 TRACE("Additionally dirtifying stage %d\n", i);
3756 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3758 This->stateBlock->lowest_disabled_stage = Stage;
3759 TRACE("New lowest disabled: %d\n", Stage);
3760 } else if(Value != WINED3DTOP_DISABLE && oldValue == WINED3DTOP_DISABLE) {
3761 /* Previously disabled stage enabled. Stages above it may need enabling
3762 * stage must be lowest_disabled_stage here, if it's bigger success is returned above,
3763 * and stages below the lowest disabled stage can't be enabled(because they are enabled already).
3765 * Again stage Stage doesn't need to be dirtified here, it is handled below.
3768 for(i = Stage + 1; i < GL_LIMITS(texture_stages); i++) {
3769 if(This->updateStateBlock->textureState[i][WINED3DTSS_COLOROP] == WINED3DTOP_DISABLE) {
3772 TRACE("Additionally dirtifying stage %d due to enable\n", i);
3773 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP));
3775 This->stateBlock->lowest_disabled_stage = i;
3776 TRACE("New lowest disabled: %d\n", i);
3778 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3779 /* TODO: Built a stage -> texture unit mapping for register combiners */
3783 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, Type));
3785 /* Rebuild the stage -> gl texture unit mapping if register combiners are supported
3786 * If there is a pixel shader there will be a 1:1 mapping, no need to touch it. SetPixelShader
3787 * will call FindTexUnitMap too.
3789 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3790 IWineD3DDeviceImpl_FindTexUnitMap(This);
3795 static HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
3796 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3797 TRACE("(%p) : requesting Stage %d, Type %d getting %d\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
3798 *pValue = This->updateStateBlock->textureState[Stage][Type];
3805 static HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
3807 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3808 IWineD3DBaseTexture *oldTexture;
3810 oldTexture = This->updateStateBlock->textures[Stage];
3811 TRACE("(%p) : Stage(%d), Texture (%p)\n", This, Stage, pTexture);
3813 #if 0 /* TODO: check so vertex textures */
3814 if (Stage >= D3DVERTEXTEXTURESAMPLER && Stage <= D3DVERTEXTEXTURESAMPLER3){
3815 This->updateStateBlock->vertexTextures[Stage - D3DVERTEXTEXTURESAMPLER] = pTexture;
3820 if(pTexture != NULL) {
3821 /* SetTexture isn't allowed on textures in WINED3DPOOL_SCRATCH;
3823 if(((IWineD3DTextureImpl*)pTexture)->resource.pool == WINED3DPOOL_SCRATCH) {
3824 WARN("(%p) Attempt to set scratch texture rejected\n", pTexture);
3825 return WINED3DERR_INVALIDCALL;
3827 This->stateBlock->textureDimensions[Stage] = IWineD3DBaseTexture_GetTextureDimensions(pTexture);
3830 TRACE("GL_LIMITS %d\n",GL_LIMITS(sampler_stages));
3831 TRACE("(%p) : oldtexture(%p)\n", This,oldTexture);
3833 This->updateStateBlock->set.textures[Stage] = TRUE;
3834 This->updateStateBlock->changed.textures[Stage] = TRUE;
3835 TRACE("(%p) : setting new texture to %p\n", This, pTexture);
3836 This->updateStateBlock->textures[Stage] = pTexture;
3838 /* Handle recording of state blocks */
3839 if (This->isRecordingState) {
3840 TRACE("Recording... not performing anything\n");
3844 if(oldTexture == pTexture) {
3845 TRACE("App is setting the same texture again, nothing to do\n");
3849 /** NOTE: MSDN says that setTexture increases the reference count,
3850 * and the the application nust set the texture back to null (or have a leaky application),
3851 * This means we should pass the refcount up to the parent
3852 *******************************/
3853 if (NULL != This->updateStateBlock->textures[Stage]) {
3854 IWineD3DBaseTextureImpl *new = (IWineD3DBaseTextureImpl *) This->updateStateBlock->textures[Stage];
3855 ULONG bindCount = InterlockedIncrement(&new->baseTexture.bindCount);
3857 IWineD3DBaseTexture_AddRef(This->updateStateBlock->textures[Stage]);
3858 if(oldTexture == NULL && Stage < MAX_TEXTURES) {
3859 /* The source arguments for color and alpha ops have different meanings when a NULL texture is bound,
3860 * so the COLOROP and ALPHAOP have to be dirtified.
3862 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
3863 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
3865 if(bindCount == 1) {
3866 new->baseTexture.sampler = Stage;
3868 /* More than one assignment? Doesn't matter, we only need one gl texture unit to use for uploading */
3872 if (NULL != oldTexture) {
3873 IWineD3DBaseTextureImpl *old = (IWineD3DBaseTextureImpl *) oldTexture;
3874 LONG bindCount = InterlockedDecrement(&old->baseTexture.bindCount);
3876 IWineD3DBaseTexture_Release(oldTexture);
3877 if(pTexture == NULL && Stage < MAX_TEXTURES) {
3878 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_COLOROP));
3879 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_TEXTURESTAGE(Stage, WINED3DTSS_ALPHAOP));
3882 if(bindCount && old->baseTexture.sampler == Stage) {
3884 /* Have to do a search for the other sampler(s) where the texture is bound to
3885 * Shouldn't happen as long as apps bind a texture only to one stage
3887 TRACE("Searcing for other sampler / stage id where the texture is bound to\n");
3888 for(i = 0; i < GL_LIMITS(sampler_stages); i++) {
3889 if(This->updateStateBlock->textures[i] == oldTexture) {
3890 old->baseTexture.sampler = i;
3897 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(Stage));
3899 /* Verify the texture unit mapping(and rebuild it if needed) if we use nvrcs and no
3900 * pixel shader is used
3902 if(GL_SUPPORT(NV_REGISTER_COMBINERS) && !This->stateBlock->pixelShader) {
3903 IWineD3DDeviceImpl_FindTexUnitMap(This);
3909 static HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3910 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3911 TRACE("(%p) : (%d /* Stage */,%p /* ppTexture */)\n", This, Stage, ppTexture);
3913 *ppTexture=This->stateBlock->textures[Stage];
3915 IWineD3DBaseTexture_AddRef(*ppTexture);
3923 static HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, WINED3DBACKBUFFER_TYPE Type,
3924 IWineD3DSurface **ppBackBuffer) {
3925 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3926 IWineD3DSwapChain *swapChain;
3929 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3931 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
3932 if (hr == WINED3D_OK) {
3933 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
3934 IWineD3DSwapChain_Release(swapChain);
3936 *ppBackBuffer = NULL;
3941 static HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
3942 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3943 WARN("(%p) : stub, calling idirect3d for now\n", This);
3944 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
3947 static HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, WINED3DDISPLAYMODE* pMode) {
3948 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3949 IWineD3DSwapChain *swapChain;
3952 if(iSwapChain > 0) {
3953 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
3954 if (hr == WINED3D_OK) {
3955 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
3956 IWineD3DSwapChain_Release(swapChain);
3958 FIXME("(%p) Error getting display mode\n", This);
3961 /* Don't read the real display mode,
3962 but return the stored mode instead. X11 can't change the color
3963 depth, and some apps are pretty angry if they SetDisplayMode from
3964 24 to 16 bpp and find out that GetDisplayMode still returns 24 bpp
3966 Also don't relay to the swapchain because with ddraw it's possible
3967 that there isn't a swapchain at all */
3968 pMode->Width = This->ddraw_width;
3969 pMode->Height = This->ddraw_height;
3970 pMode->Format = This->ddraw_format;
3971 pMode->RefreshRate = 0;
3978 static HRESULT WINAPI IWineD3DDeviceImpl_SetHWND(IWineD3DDevice *iface, HWND hWnd) {
3979 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3980 TRACE("(%p)->(%p)\n", This, hWnd);
3982 if(This->ddraw_fullscreen) {
3983 if(This->ddraw_window && This->ddraw_window != hWnd) {
3984 IWineD3DDeviceImpl_RestoreWindow(iface, This->ddraw_window);
3986 if(hWnd && This->ddraw_window != hWnd) {
3987 IWineD3DDeviceImpl_SetupFullscreenWindow(iface, hWnd);
3991 This->ddraw_window = hWnd;
3995 static HRESULT WINAPI IWineD3DDeviceImpl_GetHWND(IWineD3DDevice *iface, HWND *hWnd) {
3996 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3997 TRACE("(%p)->(%p)\n", This, hWnd);
3999 *hWnd = This->ddraw_window;
4004 * Stateblock related functions
4007 static HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4008 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4009 IWineD3DStateBlockImpl *object;
4010 HRESULT temp_result;
4013 TRACE("(%p)\n", This);
4015 if (This->isRecordingState) {
4016 return WINED3DERR_INVALIDCALL;
4019 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4020 if (NULL == object ) {
4021 FIXME("(%p)Error allocating memory for stateblock\n", This);
4022 return E_OUTOFMEMORY;
4024 TRACE("(%p) created object %p\n", This, object);
4025 object->wineD3DDevice= This;
4026 /** FIXME: object->parent = parent; **/
4027 object->parent = NULL;
4028 object->blockType = WINED3DSBT_ALL;
4030 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4032 for(i = 0; i < LIGHTMAP_SIZE; i++) {
4033 list_init(&object->lightMap[i]);
4036 temp_result = allocate_shader_constants(object);
4037 if (WINED3D_OK != temp_result)
4040 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4041 This->updateStateBlock = object;
4042 This->isRecordingState = TRUE;
4044 TRACE("(%p) recording stateblock %p\n",This , object);
4048 static HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4049 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4051 if (!This->isRecordingState) {
4052 FIXME("(%p) not recording! returning error\n", This);
4053 *ppStateBlock = NULL;
4054 return WINED3DERR_INVALIDCALL;
4057 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4058 This->isRecordingState = FALSE;
4059 This->updateStateBlock = This->stateBlock;
4060 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4061 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4062 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4067 * Scene related functions
4069 static HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4070 /* At the moment we have no need for any functionality at the beginning
4072 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4073 TRACE("(%p)\n", This);
4076 TRACE("Already in Scene, returning WINED3DERR_INVALIDCALL\n");
4077 return WINED3DERR_INVALIDCALL;
4079 This->inScene = TRUE;
4083 static HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4084 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4085 TRACE("(%p)\n", This);
4087 if(!This->inScene) {
4088 TRACE("Not in scene, returning WINED3DERR_INVALIDCALL\n");
4089 return WINED3DERR_INVALIDCALL;
4093 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4095 checkGLcall("glFlush");
4098 This->inScene = FALSE;
4102 static HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4103 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4104 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4105 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4106 IWineD3DSwapChain *swapChain = NULL;
4108 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4110 TRACE("(%p) Presenting the frame\n", This);
4112 for(i = 0 ; i < swapchains ; i ++) {
4114 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4115 TRACE("presentinng chain %d, %p\n", i, swapChain);
4116 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4117 IWineD3DSwapChain_Release(swapChain);
4123 static HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST WINED3DRECT* pRects,
4124 DWORD Flags, WINED3DCOLOR Color, float Z, DWORD Stencil) {
4125 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4126 IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *)This->render_targets[0];
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 /* In drawable flag is set below */
4186 glScissor(This->stateBlock->viewport.X,
4187 (((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height -
4188 (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4189 This->stateBlock->viewport.Width,
4190 This->stateBlock->viewport.Height);
4191 checkGLcall("glScissor");
4193 checkGLcall("glClear");
4195 if(!(target->Flags & SFLAG_INDRAWABLE) &&
4196 !(wined3d_settings.offscreen_rendering_mode == ORM_FBO && This->render_offscreen && target->Flags & SFLAG_INTEXTURE)) {
4198 if(curRect[0].x1 > 0 || curRect[0].y1 > 0 ||
4199 curRect[0].x2 < target->currentDesc.Width ||
4200 curRect[0].y2 < target->currentDesc.Height) {
4201 TRACE("Partial clear, and surface not in drawable. Blitting texture to drawable\n");
4202 blt_to_drawable(This, target);
4206 /* Now process each rect in turn */
4207 for (i = 0; i < Count; i++) {
4208 /* Note gl uses lower left, width/height */
4209 TRACE("(%p) %p Rect=(%d,%d)->(%d,%d) glRect=(%d,%d), len=%d, hei=%d\n", This, curRect,
4210 curRect[i].x1, curRect[i].y1, curRect[i].x2, curRect[i].y2,
4211 curRect[i].x1, (target->currentDesc.Height - curRect[i].y2),
4212 curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4214 /* Tests show that rectangles where x1 > x2 or y1 > y2 are ignored silently.
4215 * The rectangle is not cleared, no error is returned, but further rectanlges are
4216 * still cleared if they are valid
4218 if(curRect[i].x1 > curRect[i].x2 || curRect[i].y1 > curRect[i].y2) {
4219 TRACE("Rectangle with negative dimensions, ignoring\n");
4223 if(This->render_offscreen) {
4224 glScissor(curRect[i].x1, curRect[i].y1,
4225 curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4227 glScissor(curRect[i].x1, target->currentDesc.Height - curRect[i].y2,
4228 curRect[i].x2 - curRect[i].x1, curRect[i].y2 - curRect[i].y1);
4230 checkGLcall("glScissor");
4233 checkGLcall("glClear");
4237 /* Restore the old values (why..?) */
4238 if (Flags & WINED3DCLEAR_STENCIL) {
4239 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4241 if (Flags & WINED3DCLEAR_TARGET) {
4242 DWORD mask = This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE];
4243 glColorMask(mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4244 mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4245 mask & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4246 mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4251 /* Dirtify the target surface for now. If the surface is locked regularily, and an up to date sysmem copy exists,
4252 * it is most likely more efficient to perform a clear on the sysmem copy too isntead of downloading it
4254 if(This->render_offscreen && wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
4255 target->Flags |= SFLAG_INTEXTURE;
4256 target->Flags &= ~SFLAG_INSYSMEM;
4258 target->Flags |= SFLAG_INDRAWABLE;
4259 target->Flags &= ~(SFLAG_INTEXTURE | SFLAG_INSYSMEM);
4267 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4268 UINT PrimitiveCount) {
4270 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4272 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4273 debug_d3dprimitivetype(PrimitiveType),
4274 StartVertex, PrimitiveCount);
4276 /* The index buffer is not needed here, but restore it, otherwise it is hell to keep track of */
4277 if(This->stateBlock->streamIsUP) {
4278 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4279 This->stateBlock->streamIsUP = FALSE;
4282 if(This->stateBlock->loadBaseVertexIndex != 0) {
4283 This->stateBlock->loadBaseVertexIndex = 0;
4284 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4286 /* Account for the loading offset due to index buffers. Instead of reloading all sources correct it with the startvertex parameter */
4287 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, 0/* NumVertices */, -1 /* indxStart */,
4288 0 /* indxSize */, NULL /* indxData */, 0 /* minIndex */);
4292 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4293 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4294 WINED3DPRIMITIVETYPE PrimitiveType,
4295 UINT minIndex, UINT NumVertices, UINT startIndex, UINT primCount) {
4297 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4299 IWineD3DIndexBuffer *pIB;
4300 WINED3DINDEXBUFFER_DESC IdxBufDsc;
4303 if(This->stateBlock->streamIsUP) {
4304 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4305 This->stateBlock->streamIsUP = FALSE;
4307 pIB = This->stateBlock->pIndexData;
4308 vbo = ((IWineD3DIndexBufferImpl *) pIB)->vbo;
4310 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
4311 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4312 minIndex, NumVertices, startIndex, primCount);
4314 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4315 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4321 if(This->stateBlock->loadBaseVertexIndex != This->stateBlock->baseVertexIndex) {
4322 This->stateBlock->loadBaseVertexIndex = This->stateBlock->baseVertexIndex;
4323 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4326 drawPrimitive(iface, PrimitiveType, primCount, 0, NumVertices, startIndex,
4327 idxStride, vbo ? NULL : ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory, minIndex);
4332 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4333 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4334 UINT VertexStreamZeroStride) {
4335 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4337 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4338 debug_d3dprimitivetype(PrimitiveType),
4339 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4341 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4342 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4343 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4344 This->stateBlock->streamIsUP = TRUE;
4345 This->stateBlock->loadBaseVertexIndex = 0;
4347 /* TODO: Only mark dirty if drawing from a different UP address */
4348 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_STREAMSRC);
4350 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* start vertex */, 0 /* NumVertices */,
4351 0 /* indxStart*/, 0 /* indxSize*/, NULL /* indxData */, 0 /* indxMin */);
4353 /* MSDN specifies stream zero settings must be set to NULL */
4354 This->stateBlock->streamStride[0] = 0;
4355 This->stateBlock->streamSource[0] = NULL;
4357 /* stream zero settings set to null at end, as per the msdn. No need to mark dirty here, the app has to set
4358 * the new stream sources or use UP drawing again
4363 static HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType,
4364 UINT MinVertexIndex, UINT NumVertices,
4365 UINT PrimitiveCount, CONST void* pIndexData,
4366 WINED3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
4367 UINT VertexStreamZeroStride) {
4369 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4371 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4372 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4373 MinVertexIndex, NumVertices, PrimitiveCount, pIndexData,
4374 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4376 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4382 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4383 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4384 This->stateBlock->streamIsUP = TRUE;
4385 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4387 /* Set to 0 as per msdn. Do it now due to the stream source loading during drawPrimitive */
4388 This->stateBlock->baseVertexIndex = 0;
4389 This->stateBlock->loadBaseVertexIndex = 0;
4390 /* Mark the state dirty until we have nicer tracking of the stream source pointers */
4391 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4392 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4394 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0 /* vertexStart */, NumVertices, 0 /* indxStart */, idxStride, pIndexData, MinVertexIndex);
4396 /* MSDN specifies stream zero settings and index buffer must be set to NULL */
4397 This->stateBlock->streamSource[0] = NULL;
4398 This->stateBlock->streamStride[0] = 0;
4399 This->stateBlock->pIndexData = NULL;
4400 /* No need to mark the stream source state dirty here. Either the app calls UP drawing again, or it has to call
4401 * SetStreamSource to specify a vertex buffer
4407 static HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveStrided (IWineD3DDevice *iface, WINED3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, WineDirect3DVertexStridedData *DrawPrimStrideData) {
4408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4410 /* Mark the state dirty until we have nicer tracking
4411 * its fine to change baseVertexIndex because that call is only called by ddraw which does not need
4414 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VDECL);
4415 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_INDEXBUFFER);
4416 This->stateBlock->baseVertexIndex = 0;
4417 This->up_strided = DrawPrimStrideData;
4418 This->stateBlock->streamIsUP = TRUE;
4419 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, 0, NULL, 0);
4420 This->up_strided = NULL;
4423 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4424 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4425 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4426 HRESULT hr = WINED3D_OK;
4427 WINED3DRESOURCETYPE sourceType;
4428 WINED3DRESOURCETYPE destinationType;
4431 /* TODO: think about moving the code into IWineD3DBaseTexture */
4433 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4435 /* verify that the source and destination textures aren't NULL */
4436 if (NULL == pSourceTexture || NULL == pDestinationTexture) {
4437 WARN("(%p) : source (%p) and destination (%p) textures must not be NULL, returning WINED3DERR_INVALIDCALL\n",
4438 This, pSourceTexture, pDestinationTexture);
4439 hr = WINED3DERR_INVALIDCALL;
4442 if (pSourceTexture == pDestinationTexture) {
4443 WARN("(%p) : source (%p) and destination (%p) textures must be different, returning WINED3DERR_INVALIDCALL\n",
4444 This, pSourceTexture, pDestinationTexture);
4445 hr = WINED3DERR_INVALIDCALL;
4447 /* Verify that the source and destination textures are the same type */
4448 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4449 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4451 if (sourceType != destinationType) {
4452 WARN("(%p) Sorce and destination types must match, returning WINED3DERR_INVALIDCALL\n",
4454 hr = WINED3DERR_INVALIDCALL;
4457 /* check that both textures have the identical numbers of levels */
4458 if (IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) != IWineD3DBaseTexture_GetLevelCount(pSourceTexture)) {
4459 WARN("(%p) : source (%p) and destination (%p) textures must have identicle numbers of levels, returning WINED3DERR_INVALIDCALL\n", This, pSourceTexture, pDestinationTexture);
4460 hr = WINED3DERR_INVALIDCALL;
4463 if (WINED3D_OK == hr) {
4465 /* Make sure that the destination texture is loaded */
4466 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4468 /* Update every surface level of the texture */
4469 levels = IWineD3DBaseTexture_GetLevelCount(pDestinationTexture);
4471 switch (sourceType) {
4472 case WINED3DRTYPE_TEXTURE:
4474 IWineD3DSurface *srcSurface;
4475 IWineD3DSurface *destSurface;
4477 for (i = 0 ; i < levels ; ++i) {
4478 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pSourceTexture, i, &srcSurface);
4479 IWineD3DTexture_GetSurfaceLevel((IWineD3DTexture *)pDestinationTexture, i, &destSurface);
4480 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4481 IWineD3DSurface_Release(srcSurface);
4482 IWineD3DSurface_Release(destSurface);
4483 if (WINED3D_OK != hr) {
4484 WARN("(%p) : Call to update surface failed\n", This);
4490 case WINED3DRTYPE_CUBETEXTURE:
4492 IWineD3DSurface *srcSurface;
4493 IWineD3DSurface *destSurface;
4494 WINED3DCUBEMAP_FACES faceType;
4496 for (i = 0 ; i < levels ; ++i) {
4497 /* Update each cube face */
4498 for (faceType = WINED3DCUBEMAP_FACE_POSITIVE_X; faceType <= WINED3DCUBEMAP_FACE_NEGATIVE_Z; ++faceType){
4499 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pSourceTexture, faceType, i, &srcSurface);
4500 if (WINED3D_OK != hr) {
4501 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4503 TRACE("Got srcSurface %p\n", srcSurface);
4505 hr = IWineD3DCubeTexture_GetCubeMapSurface((IWineD3DCubeTexture *)pDestinationTexture, faceType, i, &destSurface);
4506 if (WINED3D_OK != hr) {
4507 FIXME("(%p) : Failed to get src cube surface facetype %d, level %d\n", This, faceType, i);
4509 TRACE("Got desrSurface %p\n", destSurface);
4511 hr = IWineD3DDevice_UpdateSurface(iface, srcSurface, NULL, destSurface, NULL);
4512 IWineD3DSurface_Release(srcSurface);
4513 IWineD3DSurface_Release(destSurface);
4514 if (WINED3D_OK != hr) {
4515 WARN("(%p) : Call to update surface failed\n", This);
4522 #if 0 /* TODO: Add support for volume textures */
4523 case WINED3DRTYPE_VOLUMETEXTURE:
4525 IWineD3DVolume srcVolume = NULL;
4526 IWineD3DSurface destVolume = NULL;
4528 for (i = 0 ; i < levels ; ++i) {
4529 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pSourceTexture, i, &srcVolume);
4530 IWineD3DVolumeTexture_GetVolume((IWineD3DVolumeTexture *)pDestinationTexture, i, &destVolume);
4531 hr = IWineD3DFoo_UpdateVolume(iface, srcVolume, NULL, destVolume, NULL);
4532 IWineD3DVolume_Release(srcSurface);
4533 IWineD3DVolume_Release(destSurface);
4534 if (WINED3D_OK != hr) {
4535 WARN("(%p) : Call to update volume failed\n", This);
4543 FIXME("(%p) : Unsupported source and destination type\n", This);
4544 hr = WINED3DERR_INVALIDCALL;
4551 static HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4552 IWineD3DSwapChain *swapChain;
4554 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4555 if(hr == WINED3D_OK) {
4556 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4557 IWineD3DSwapChain_Release(swapChain);
4562 static HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4563 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4564 /* return a sensible default */
4566 /* TODO: If the window is minimized then validate device should return something other than WINED3D_OK */
4567 FIXME("(%p) : stub\n", This);
4571 static HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4572 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4574 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4575 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4576 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4577 return WINED3DERR_INVALIDCALL;
4579 for (j = 0; j < 256; ++j) {
4580 This->palettes[PaletteNumber][j].peRed = pEntries[j].peRed;
4581 This->palettes[PaletteNumber][j].peGreen = pEntries[j].peGreen;
4582 This->palettes[PaletteNumber][j].peBlue = pEntries[j].peBlue;
4583 This->palettes[PaletteNumber][j].peFlags = pEntries[j].peFlags;
4585 TRACE("(%p) : returning\n", This);
4589 static HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4590 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4592 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4593 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4594 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4595 return WINED3DERR_INVALIDCALL;
4597 for (j = 0; j < 256; ++j) {
4598 pEntries[j].peRed = This->palettes[PaletteNumber][j].peRed;
4599 pEntries[j].peGreen = This->palettes[PaletteNumber][j].peGreen;
4600 pEntries[j].peBlue = This->palettes[PaletteNumber][j].peBlue;
4601 pEntries[j].peFlags = This->palettes[PaletteNumber][j].peFlags;
4603 TRACE("(%p) : returning\n", This);
4607 static HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4609 TRACE("(%p) : PaletteNumber %u\n", This, PaletteNumber);
4610 if ( PaletteNumber < 0 || PaletteNumber >= MAX_PALETTES) {
4611 WARN("(%p) : (%u) Out of range 0-%u, returning Invalid Call\n", This, PaletteNumber, MAX_PALETTES);
4612 return WINED3DERR_INVALIDCALL;
4614 /*TODO: stateblocks */
4615 This->currentPalette = PaletteNumber;
4616 TRACE("(%p) : returning\n", This);
4620 static HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4621 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4622 if (PaletteNumber == NULL) {
4623 WARN("(%p) : returning Invalid Call\n", This);
4624 return WINED3DERR_INVALIDCALL;
4626 /*TODO: stateblocks */
4627 *PaletteNumber = This->currentPalette;
4628 TRACE("(%p) : returning %u\n", This, *PaletteNumber);
4632 static HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4633 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4634 static BOOL showFixmes = TRUE;
4636 FIXME("(%p) : stub\n", This);
4640 This->softwareVertexProcessing = bSoftware;
4645 static BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4646 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4647 static BOOL showFixmes = TRUE;
4649 FIXME("(%p) : stub\n", This);
4652 return This->softwareVertexProcessing;
4656 static HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, WINED3DRASTER_STATUS* pRasterStatus) {
4657 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4658 IWineD3DSwapChain *swapChain;
4661 TRACE("(%p) : SwapChain %d returning %p\n", This, iSwapChain, pRasterStatus);
4663 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4664 if(hr == WINED3D_OK){
4665 hr = IWineD3DSwapChain_GetRasterStatus(swapChain, pRasterStatus);
4666 IWineD3DSwapChain_Release(swapChain);
4668 FIXME("(%p) IWineD3DSwapChain_GetRasterStatus returned in error\n", This);
4674 static HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4675 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4676 static BOOL showfixmes = TRUE;
4677 if(nSegments != 0.0f) {
4679 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4686 static float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4687 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4688 static BOOL showfixmes = TRUE;
4690 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4696 static HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4697 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4698 /** TODO: remove casts to IWineD3DSurfaceImpl
4699 * NOTE: move code to surface to accomplish this
4700 ****************************************/
4701 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4702 int srcWidth, srcHeight;
4703 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4704 WINED3DFORMAT destFormat, srcFormat;
4706 int srcLeft, destLeft, destTop;
4707 WINED3DPOOL srcPool, destPool;
4709 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4710 glDescriptor *glDescription = NULL;
4712 WINED3DSURFACE_DESC winedesc;
4714 TRACE("(%p) : Source (%p) Rect (%p) Destination (%p) Point(%p)\n", This, pSourceSurface, pSourceRect, pDestinationSurface, pDestPoint);
4715 memset(&winedesc, 0, sizeof(winedesc));
4716 winedesc.Width = &srcSurfaceWidth;
4717 winedesc.Height = &srcSurfaceHeight;
4718 winedesc.Pool = &srcPool;
4719 winedesc.Format = &srcFormat;
4721 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4723 winedesc.Width = &destSurfaceWidth;
4724 winedesc.Height = &destSurfaceHeight;
4725 winedesc.Pool = &destPool;
4726 winedesc.Format = &destFormat;
4727 winedesc.Size = &destSize;
4729 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4731 if(srcPool != WINED3DPOOL_SYSTEMMEM || destPool != WINED3DPOOL_DEFAULT){
4732 WARN("source %p must be SYSTEMMEM and dest %p must be DEFAULT, returning WINED3DERR_INVALIDCALL\n", pSourceSurface, pDestinationSurface);
4733 return WINED3DERR_INVALIDCALL;
4736 if (destFormat == WINED3DFMT_UNKNOWN) {
4737 TRACE("(%p) : Converting destination surface from WINED3DFMT_UNKNOWN to the source format\n", This);
4738 IWineD3DSurface_SetFormat(pDestinationSurface, srcFormat);
4740 /* Get the update surface description */
4741 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4745 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4746 GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
4747 checkGLcall("glActiveTextureARB");
4750 /* Make sure the surface is loaded and up to date */
4751 IWineD3DSurface_PreLoad(pDestinationSurface);
4753 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4755 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4756 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4757 srcHeight = pSourceRect ? pSourceRect->bottom - pSourceRect->top : srcSurfaceHeight;
4758 srcLeft = pSourceRect ? pSourceRect->left : 0;
4759 destLeft = pDestPoint ? pDestPoint->x : 0;
4760 destTop = pDestPoint ? pDestPoint->y : 0;
4763 /* This function doesn't support compressed textures
4764 the pitch is just bytesPerPixel * width */
4765 if(srcWidth != srcSurfaceWidth || srcLeft ){
4766 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4767 offset += srcLeft * pSrcSurface->bytesPerPixel;
4768 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4770 /* TODO DXT formats */
4772 if(pSourceRect != NULL && pSourceRect->top != 0){
4773 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4775 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4777 ,glDescription->level
4782 ,glDescription->glFormat
4783 ,glDescription->glType
4784 ,IWineD3DSurface_GetData(pSourceSurface)
4788 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4790 /* need to lock the surface to get the data */
4791 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4794 /* TODO: Cube and volume support */
4796 /* not a whole row so we have to do it a line at a time */
4799 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4800 const unsigned char* data =((const unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4802 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4804 glTexSubImage2D(glDescription->target
4805 ,glDescription->level
4810 ,glDescription->glFormat
4811 ,glDescription->glType
4812 ,data /* could be quicker using */
4817 } else { /* Full width, so just write out the whole texture */
4819 if (WINED3DFMT_DXT1 == destFormat ||
4820 WINED3DFMT_DXT2 == destFormat ||
4821 WINED3DFMT_DXT3 == destFormat ||
4822 WINED3DFMT_DXT4 == destFormat ||
4823 WINED3DFMT_DXT5 == destFormat) {
4824 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4825 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4826 /* FIXME: The easy way to do this is to lock the destination, and copy the bits across */
4827 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4828 } if (destFormat != srcFormat) {
4829 FIXME("Updating mixed format compressed texture is not curretly support\n");
4831 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4832 glDescription->level,
4833 glDescription->glFormatInternal,
4838 IWineD3DSurface_GetData(pSourceSurface));
4841 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
4846 glTexSubImage2D(glDescription->target
4847 ,glDescription->level
4852 ,glDescription->glFormat
4853 ,glDescription->glType
4854 ,IWineD3DSurface_GetData(pSourceSurface)
4858 checkGLcall("glTexSubImage2D");
4862 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags &= ~SFLAG_INSYSMEM;
4863 ((IWineD3DSurfaceImpl *)pDestinationSurface)->Flags |= SFLAG_INTEXTURE;
4864 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_SAMPLER(0));
4869 /* Implementation details at http://developer.nvidia.com/attach/6494
4871 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
4872 hmm.. no longer supported use
4873 OpenGL evaluators or tessellate surfaces within your application.
4876 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
4877 static HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DRECTPATCH_INFO* pRectPatchInfo) {
4878 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4879 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p)\n", This, Handle, pNumSegs, pRectPatchInfo);
4880 FIXME("(%p) : Stub\n", This);
4885 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
4886 static HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST WINED3DTRIPATCH_INFO* pTriPatchInfo) {
4887 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4888 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p)\n", This, Handle, pNumSegs, pTriPatchInfo);
4889 FIXME("(%p) : Stub\n", This);
4893 static HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
4894 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4895 TRACE("(%p) Handle(%d)\n", This, Handle);
4896 FIXME("(%p) : Stub\n", This);
4900 static HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST WINED3DRECT* pRect, WINED3DCOLOR color) {
4901 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4902 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *) pSurface;
4904 TRACE("(%p) Colour fill Surface: %p rect: %p color: %d\n", This, pSurface, pRect, color);
4906 if (surface->resource.pool != WINED3DPOOL_DEFAULT && surface->resource.pool != WINED3DPOOL_SYSTEMMEM) {
4907 FIXME("call to colorfill with non WINED3DPOOL_DEFAULT or WINED3DPOOL_SYSTEMMEM surface\n");
4908 return WINED3DERR_INVALIDCALL;
4911 /* Just forward this to the DirectDraw blitting engine */
4912 memset(&BltFx, 0, sizeof(BltFx));
4913 BltFx.dwSize = sizeof(BltFx);
4914 BltFx.u5.dwFillColor = color;
4915 return IWineD3DSurface_Blt(pSurface, (RECT *) pRect, NULL, NULL, DDBLT_COLORFILL, &BltFx);
4918 /* rendertarget and deptth stencil functions */
4919 static HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
4920 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4922 if (RenderTargetIndex >= GL_LIMITS(buffers)) {
4923 ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
4924 return WINED3DERR_INVALIDCALL;
4927 *ppRenderTarget = This->render_targets[RenderTargetIndex];
4928 TRACE("(%p) : RenderTarget %d Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
4929 /* Note inc ref on returned surface */
4930 if(*ppRenderTarget != NULL)
4931 IWineD3DSurface_AddRef(*ppRenderTarget);
4935 static HRESULT WINAPI IWineD3DDeviceImpl_SetFrontBackBuffers(IWineD3DDevice *iface, IWineD3DSurface *Front, IWineD3DSurface *Back) {
4936 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4937 IWineD3DSurfaceImpl *FrontImpl = (IWineD3DSurfaceImpl *) Front;
4938 IWineD3DSurfaceImpl *BackImpl = (IWineD3DSurfaceImpl *) Back;
4939 IWineD3DSwapChainImpl *Swapchain;
4942 TRACE("(%p)->(%p,%p)\n", This, FrontImpl, BackImpl);
4944 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &Swapchain);
4945 if(hr != WINED3D_OK) {
4946 ERR("Can't get the swapchain\n");
4950 /* Make sure to release the swapchain */
4951 IWineD3DSwapChain_Release((IWineD3DSwapChain *) Swapchain);
4953 if(FrontImpl && !(FrontImpl->resource.usage & WINED3DUSAGE_RENDERTARGET) ) {
4954 ERR("Trying to set a front buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
4955 return WINED3DERR_INVALIDCALL;
4957 else if(BackImpl && !(BackImpl->resource.usage & WINED3DUSAGE_RENDERTARGET)) {
4958 ERR("Trying to set a back buffer which doesn't have WINED3DUSAGE_RENDERTARGET usage\n");
4959 return WINED3DERR_INVALIDCALL;
4962 if(Swapchain->frontBuffer != Front) {
4963 TRACE("Changing the front buffer from %p to %p\n", Swapchain->frontBuffer, Front);
4965 if(Swapchain->frontBuffer)
4966 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, NULL);
4967 Swapchain->frontBuffer = Front;
4969 if(Swapchain->frontBuffer) {
4970 IWineD3DSurface_SetContainer(Swapchain->frontBuffer, (IWineD3DBase *) Swapchain);
4974 if(Back && !Swapchain->backBuffer) {
4975 /* We need memory for the back buffer array - only one back buffer this way */
4976 Swapchain->backBuffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurface *));
4977 if(!Swapchain->backBuffer) {
4978 ERR("Out of memory\n");
4979 return E_OUTOFMEMORY;
4983 if(Swapchain->backBuffer[0] != Back) {
4984 TRACE("Changing the back buffer from %p to %p\n", Swapchain->backBuffer, Back);
4986 if(!Swapchain->backBuffer[0]) {
4987 /* GL was told to draw to the front buffer at creation,
4990 glDrawBuffer(GL_BACK);
4991 checkGLcall("glDrawBuffer(GL_BACK)");
4992 /* Set the backbuffer count to 1 because other code uses it to fing the back buffers */
4993 Swapchain->presentParms.BackBufferCount = 1;
4995 /* That makes problems - disable for now */
4996 /* glDrawBuffer(GL_FRONT); */
4997 checkGLcall("glDrawBuffer(GL_FRONT)");
4998 /* We have lost our back buffer, set this to 0 to avoid confusing other code */
4999 Swapchain->presentParms.BackBufferCount = 0;
5003 if(Swapchain->backBuffer[0])
5004 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], NULL);
5005 Swapchain->backBuffer[0] = Back;
5007 if(Swapchain->backBuffer[0]) {
5008 IWineD3DSurface_SetContainer(Swapchain->backBuffer[0], (IWineD3DBase *) Swapchain);
5010 HeapFree(GetProcessHeap(), 0, Swapchain->backBuffer);
5018 static HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5019 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5020 *ppZStencilSurface = This->depthStencilBuffer;
5021 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5023 if(*ppZStencilSurface != NULL) {
5024 /* Note inc ref on returned surface */
5025 IWineD3DSurface_AddRef(*ppZStencilSurface);
5030 static void bind_fbo(IWineD3DDevice *iface) {
5031 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5034 GL_EXTCALL(glGenFramebuffersEXT(1, &This->fbo));
5035 checkGLcall("glGenFramebuffersEXT()");
5037 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
5038 checkGLcall("glBindFramebuffer()");
5041 /* TODO: Handle stencil attachments */
5042 static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_stencil) {
5043 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5044 IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
5046 This->depth_copy_state = WINED3D_DCS_NO_COPY;
5050 if (depth_stencil_impl) {
5051 GLenum texttarget, target;
5052 GLint old_binding = 0;
5054 IWineD3DSurface_PreLoad(depth_stencil);
5055 texttarget = depth_stencil_impl->glDescription.target;
5056 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5058 glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5059 glBindTexture(target, depth_stencil_impl->glDescription.textureName);
5060 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
5061 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
5062 glTexParameteri(target, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
5063 glBindTexture(target, old_binding);
5065 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, texttarget, depth_stencil_impl->glDescription.textureName, 0));
5066 checkGLcall("glFramebufferTexture2DEXT()");
5068 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, 0, 0));
5069 checkGLcall("glFramebufferTexture2DEXT()");
5072 if (!This->render_offscreen) {
5073 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5074 checkGLcall("glBindFramebuffer()");
5078 void set_render_target_fbo(IWineD3DDevice *iface, DWORD idx, IWineD3DSurface *render_target) {
5079 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5080 IWineD3DSurfaceImpl *rtimpl = (IWineD3DSurfaceImpl *)render_target;
5082 if (idx >= GL_LIMITS(buffers)) {
5083 ERR("%p : Trying to set render target %d, but only %d supported\n", This, idx, GL_LIMITS(buffers));
5089 GLenum texttarget, target;
5090 GLint old_binding = 0;
5092 IWineD3DSurface_PreLoad(render_target);
5093 texttarget = rtimpl->glDescription.target;
5094 target = texttarget == GL_TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP_ARB;
5096 glGetIntegerv(texttarget == GL_TEXTURE_2D ? GL_TEXTURE_BINDING_2D : GL_TEXTURE_BINDING_CUBE_MAP_ARB, &old_binding);
5097 glBindTexture(target, rtimpl->glDescription.textureName);
5098 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
5099 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
5100 glBindTexture(target, old_binding);
5102 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, texttarget, rtimpl->glDescription.textureName, 0));
5103 checkGLcall("glFramebufferTexture2DEXT()");
5105 This->draw_buffers[idx] = GL_COLOR_ATTACHMENT0_EXT + idx;
5107 GL_EXTCALL(glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT + idx, GL_TEXTURE_2D, 0, 0));
5108 checkGLcall("glFramebufferTexture2DEXT()");
5110 This->draw_buffers[idx] = GL_NONE;
5113 if (GL_SUPPORT(ARB_DRAW_BUFFERS)) {
5114 GL_EXTCALL(glDrawBuffersARB(GL_LIMITS(buffers), This->draw_buffers));
5115 checkGLcall("glDrawBuffers()");
5118 if (!This->render_offscreen) {
5119 GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
5120 checkGLcall("glBindFramebuffer()");
5124 static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5125 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5126 WINED3DVIEWPORT viewport;
5128 TRACE("(%p) : Setting rendertarget %d to %p\n", This, RenderTargetIndex, pRenderTarget);
5130 if (RenderTargetIndex >= GL_LIMITS(buffers)) {
5131 ERR("(%p) : Only %d render targets are supported.\n", This, GL_LIMITS(buffers));
5132 return WINED3DERR_INVALIDCALL;
5135 /* MSDN says that null disables the render target
5136 but a device must always be associated with a render target
5137 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5139 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5142 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5143 FIXME("Trying to set render target 0 to NULL\n");
5144 return WINED3DERR_INVALIDCALL;
5146 if (pRenderTarget && !((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & WINED3DUSAGE_RENDERTARGET) {
5147 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);
5148 return WINED3DERR_INVALIDCALL;
5151 /* If we are trying to set what we already have, don't bother */
5152 if (pRenderTarget == This->render_targets[RenderTargetIndex]) {
5153 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5156 if(pRenderTarget) IWineD3DSurface_AddRef(pRenderTarget);
5157 if(This->render_targets[RenderTargetIndex]) IWineD3DSurface_Release(This->render_targets[RenderTargetIndex]);
5158 This->render_targets[RenderTargetIndex] = pRenderTarget;
5160 /* Render target 0 is special */
5161 if(RenderTargetIndex == 0) {
5162 /* Finally, reset the viewport as the MSDN states. */
5163 viewport.Height = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Height;
5164 viewport.Width = ((IWineD3DSurfaceImpl *)This->render_targets[0])->currentDesc.Width;
5167 viewport.MaxZ = 1.0f;
5168 viewport.MinZ = 0.0f;
5169 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5170 /* Make sure the viewport state is dirty, because the render_offscreen thing affects it.
5171 * SetViewport may catch NOP viewport changes, which would occur when switching between equally sized targets
5173 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_VIEWPORT);
5175 /* Activate the new render target for now. This shouldn't stay here, but is needed until all methods using gl activate the
5177 * Use resourceload usage, this will just set the drawables and context but not apply any states. The stateblock may be
5178 * incomplete or incorrect when SetRenderTarget is called. DrawPrim() will apply the states when it is called.
5180 ActivateContext(This, This->render_targets[0], CTXUSAGE_RESOURCELOAD);
5182 /* We only get more than 1 render target with fbos, so no need to check the offscreen rendering method */
5183 set_render_target_fbo(iface, RenderTargetIndex, pRenderTarget);
5188 static HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5189 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5190 HRESULT hr = WINED3D_OK;
5191 IWineD3DSurface *tmp;
5193 TRACE("(%p) Swapping z-buffer\n",This);
5195 if (pNewZStencil == This->stencilBufferTarget) {
5196 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5198 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5199 * depending on the renter target implementation being used.
5200 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5201 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5202 * stencil buffer and incure an extra memory overhead
5203 ******************************************************/
5205 tmp = This->stencilBufferTarget;
5206 This->stencilBufferTarget = pNewZStencil;
5207 /* should we be calling the parent or the wined3d surface? */
5208 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5209 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5212 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO) {
5213 set_depth_stencil_fbo(iface, pNewZStencil);
5216 if((!tmp && pNewZStencil) || (!pNewZStencil && tmp)) {
5217 /* Swapping NULL / non NULL depth stencil affects the depth and tests */
5218 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_ZENABLE));
5219 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILENABLE));
5220 IWineD3DDeviceImpl_MarkStateDirty(This, STATE_RENDER(WINED3DRS_STENCILWRITEMASK));
5227 static HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5228 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5229 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5230 /* TODO: the use of Impl is deprecated. */
5231 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5233 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5235 /* some basic validation checks */
5236 if(This->cursorTexture) {
5238 glDeleteTextures(1, &This->cursorTexture);
5240 This->cursorTexture = 0;
5244 /* MSDN: Cursor must be A8R8G8B8 */
5245 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5246 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5247 return WINED3DERR_INVALIDCALL;
5250 /* MSDN: Cursor must be smaller than the display mode */
5251 if(pSur->currentDesc.Width > This->ddraw_width ||
5252 pSur->currentDesc.Height > This->ddraw_height) {
5253 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);
5254 return WINED3DERR_INVALIDCALL;
5257 /* TODO: MSDN: Cursor sizes must be a power of 2 */
5258 /* This is to tell our texture code to load a SCRATCH surface. This allows us to use out
5259 * Texture and Blitting code to draw the cursor
5261 pSur->Flags |= SFLAG_FORCELOAD;
5262 IWineD3DSurface_PreLoad(pCursorBitmap);
5263 pSur->Flags &= ~SFLAG_FORCELOAD;
5264 /* Do not store the surface's pointer because the application may release
5265 * it after setting the cursor image. Windows doesn't addref the set surface, so we can't
5266 * do this either without creating circular refcount dependencies. Copy out the gl texture instead.
5268 This->cursorTexture = pSur->glDescription.textureName;
5269 This->cursorWidth = pSur->currentDesc.Width;
5270 This->cursorHeight = pSur->currentDesc.Height;
5271 pSur->glDescription.textureName = 0; /* Prevent the texture from being changed or deleted */
5274 This->xHotSpot = XHotSpot;
5275 This->yHotSpot = YHotSpot;
5279 static void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5280 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5281 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5283 This->xScreenSpace = XScreenSpace;
5284 This->yScreenSpace = YScreenSpace;
5290 static BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5291 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5292 BOOL oldVisible = This->bCursorVisible;
5295 TRACE("(%p) : visible(%d)\n", This, bShow);
5297 if(This->cursorTexture)
5298 This->bCursorVisible = bShow;
5300 * When ShowCursor is first called it should make the cursor appear at the OS's last
5301 * known cursor position. Because of this, some applications just repetitively call
5302 * ShowCursor in order to update the cursor's position. This behavior is undocumented.
5305 This->xScreenSpace = pt.x;
5306 This->yScreenSpace = pt.y;
5311 static HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5312 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5313 TRACE("(%p) : state (%u)\n", This, This->state);
5314 /* TODO: Implement wrapping of the WndProc so that mimimize and maxamise can be monitored and the states adjusted. */
5315 switch (This->state) {
5318 case WINED3DERR_DEVICELOST:
5320 ResourceList *resourceList = This->resources;
5321 while (NULL != resourceList) {
5322 if (((IWineD3DResourceImpl *)resourceList->resource)->resource.pool == WINED3DPOOL_DEFAULT /* TODO: IWineD3DResource_GetPool(resourceList->resource)*/)
5323 return WINED3DERR_DEVICENOTRESET;
5324 resourceList = resourceList->next;
5326 return WINED3DERR_DEVICELOST;
5328 case WINED3DERR_DRIVERINTERNALERROR:
5329 return WINED3DERR_DRIVERINTERNALERROR;
5333 return WINED3DERR_DRIVERINTERNALERROR;
5337 static HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5339 /** FIXME: Resource tracking needs to be done,
5340 * The closes we can do to this is set the priorities of all managed textures low
5341 * and then reset them.
5342 ***********************************************************/
5343 FIXME("(%p) : stub\n", This);
5347 static void updateSurfaceDesc(IWineD3DSurfaceImpl *surface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5348 IWineD3DDeviceImpl *This = surface->resource.wineD3DDevice; /* for GL_SUPPORT */
5350 /* Reallocate proper memory for the front and back buffer and adjust their sizes */
5351 if(surface->Flags & SFLAG_DIBSECTION) {
5352 /* Release the DC */
5353 SelectObject(surface->hDC, surface->dib.holdbitmap);
5354 DeleteDC(surface->hDC);
5355 /* Release the DIB section */
5356 DeleteObject(surface->dib.DIBsection);
5357 surface->dib.bitmap_data = NULL;
5358 surface->resource.allocatedMemory = NULL;
5359 surface->Flags &= ~SFLAG_DIBSECTION;
5361 surface->currentDesc.Width = pPresentationParameters->BackBufferWidth;
5362 surface->currentDesc.Height = pPresentationParameters->BackBufferHeight;
5363 if (GL_SUPPORT(ARB_TEXTURE_NON_POWER_OF_TWO)) {
5364 surface->pow2Width = pPresentationParameters->BackBufferWidth;
5365 surface->pow2Height = pPresentationParameters->BackBufferHeight;
5367 surface->pow2Width = surface->pow2Height = 1;
5368 while (surface->pow2Width < pPresentationParameters->BackBufferWidth) surface->pow2Width <<= 1;
5369 while (surface->pow2Height < pPresentationParameters->BackBufferHeight) surface->pow2Height <<= 1;
5371 if(surface->glDescription.textureName) {
5373 glDeleteTextures(1, &surface->glDescription.textureName);
5375 surface->glDescription.textureName = 0;
5377 if(surface->pow2Width != pPresentationParameters->BackBufferWidth ||
5378 surface->pow2Height != pPresentationParameters->BackBufferHeight) {
5379 surface->Flags |= SFLAG_NONPOW2;
5381 surface->Flags &= ~SFLAG_NONPOW2;
5383 HeapFree(GetProcessHeap(), 0, surface->resource.allocatedMemory);
5384 surface->resource.size = IWineD3DSurface_GetPitch((IWineD3DSurface *) surface) * surface->pow2Width;
5387 static HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
5388 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5389 IWineD3DSwapChainImpl *swapchain;
5391 BOOL DisplayModeChanged = FALSE;
5392 WINED3DDISPLAYMODE mode;
5393 TRACE("(%p)\n", This);
5395 hr = IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **) &swapchain);
5397 ERR("Failed to get the first implicit swapchain\n");
5401 /* Is it necessary to recreate the gl context? Actually every setting can be changed
5402 * on an existing gl context, so there's no real need for recreation.
5404 * TODO: Figure out how Reset influences resources in D3DPOOL_DEFAULT, D3DPOOL_SYSTEMMEMORY and D3DPOOL_MANAGED
5406 * TODO: Figure out what happens to explicit swapchains, or if we have more than one implicit swapchain
5408 TRACE("New params:\n");
5409 TRACE("BackBufferWidth = %d\n", pPresentationParameters->BackBufferWidth);
5410 TRACE("BackBufferHeight = %d\n", pPresentationParameters->BackBufferHeight);
5411 TRACE("BackBufferFormat = %s\n", debug_d3dformat(pPresentationParameters->BackBufferFormat));
5412 TRACE("BackBufferCount = %d\n", pPresentationParameters->BackBufferCount);
5413 TRACE("MultiSampleType = %d\n", pPresentationParameters->MultiSampleType);
5414 TRACE("MultiSampleQuality = %d\n", pPresentationParameters->MultiSampleQuality);
5415 TRACE("SwapEffect = %d\n", pPresentationParameters->SwapEffect);
5416 TRACE("hDeviceWindow = %p\n", pPresentationParameters->hDeviceWindow);
5417 TRACE("Windowed = %s\n", pPresentationParameters->Windowed ? "true" : "false");
5418 TRACE("EnableAutoDepthStencil = %s\n", pPresentationParameters->EnableAutoDepthStencil ? "true" : "false");
5419 TRACE("Flags = %08x\n", pPresentationParameters->Flags);
5420 TRACE("FullScreen_RefreshRateInHz = %d\n", pPresentationParameters->FullScreen_RefreshRateInHz);
5421 TRACE("PresentationInterval = %d\n", pPresentationParameters->PresentationInterval);
5423 /* No special treatment of these parameters. Just store them */
5424 swapchain->presentParms.SwapEffect = pPresentationParameters->SwapEffect;
5425 swapchain->presentParms.Flags = pPresentationParameters->Flags;
5426 swapchain->presentParms.PresentationInterval = pPresentationParameters->PresentationInterval;
5427 swapchain->presentParms.FullScreen_RefreshRateInHz = pPresentationParameters->FullScreen_RefreshRateInHz;
5429 /* What to do about these? */
5430 if(pPresentationParameters->BackBufferCount != 0 &&
5431 pPresentationParameters->BackBufferCount != swapchain->presentParms.BackBufferCount) {
5432 ERR("Cannot change the back buffer count yet\n");
5434 if(pPresentationParameters->BackBufferFormat != WINED3DFMT_UNKNOWN &&
5435 pPresentationParameters->BackBufferFormat != swapchain->presentParms.BackBufferFormat) {
5436 ERR("Cannot change the back buffer format yet\n");
5438 if(pPresentationParameters->hDeviceWindow != NULL &&
5439 pPresentationParameters->hDeviceWindow != swapchain->presentParms.hDeviceWindow) {
5440 ERR("Cannot change the device window yet\n");
5442 if(pPresentationParameters->EnableAutoDepthStencil != swapchain->presentParms.EnableAutoDepthStencil) {
5443 ERR("What do do about a changed auto depth stencil parameter?\n");
5446 if(pPresentationParameters->Windowed) {
5447 mode.Width = swapchain->orig_width;
5448 mode.Height = swapchain->orig_height;
5449 mode.RefreshRate = 0;
5450 mode.Format = swapchain->presentParms.BackBufferFormat;
5452 mode.Width = pPresentationParameters->BackBufferWidth;
5453 mode.Height = pPresentationParameters->BackBufferHeight;
5454 mode.RefreshRate = pPresentationParameters->FullScreen_RefreshRateInHz;
5455 mode.Format = swapchain->presentParms.BackBufferFormat;
5458 /* Should Width == 800 && Height == 0 set 800x600? */
5459 if(pPresentationParameters->BackBufferWidth != 0 && pPresentationParameters->BackBufferHeight != 0 &&
5460 (pPresentationParameters->BackBufferWidth != swapchain->presentParms.BackBufferWidth ||
5461 pPresentationParameters->BackBufferHeight != swapchain->presentParms.BackBufferHeight))
5468 vp.Width = pPresentationParameters->BackBufferWidth;
5469 vp.Height = pPresentationParameters->BackBufferHeight;
5473 if(!pPresentationParameters->Windowed) {
5474 DisplayModeChanged = TRUE;
5476 swapchain->presentParms.BackBufferWidth = pPresentationParameters->BackBufferWidth;
5477 swapchain->presentParms.BackBufferHeight = pPresentationParameters->BackBufferHeight;
5479 updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->frontBuffer, pPresentationParameters);
5480 for(i = 0; i < swapchain->presentParms.BackBufferCount; i++) {
5481 updateSurfaceDesc((IWineD3DSurfaceImpl *)swapchain->backBuffer[i], pPresentationParameters);
5484 /* Now set the new viewport */
5485 IWineD3DDevice_SetViewport(iface, &vp);
5488 if((pPresentationParameters->Windowed && !swapchain->presentParms.Windowed) ||
5489 (swapchain->presentParms.Windowed && !pPresentationParameters->Windowed) ||
5490 DisplayModeChanged) {
5492 /* Switching to fullscreen? Change to fullscreen mode, THEN change the screen res */
5493 if(!pPresentationParameters->Windowed) {
5494 IWineD3DDevice_SetFullscreen(iface, TRUE);
5497 IWineD3DDevice_SetDisplayMode(iface, 0, &mode);
5499 /* Switching out of fullscreen mode? First set the original res, then change the window */
5500 if(pPresentationParameters->Windowed) {
5501 IWineD3DDevice_SetFullscreen(iface, FALSE);
5503 swapchain->presentParms.Windowed = pPresentationParameters->Windowed;
5506 IWineD3DSwapChain_Release((IWineD3DSwapChain *) swapchain);
5510 static HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5511 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5512 /** FIXME: always true at the moment **/
5513 if(!bEnableDialogs) {
5514 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5520 static HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, WINED3DDEVICE_CREATION_PARAMETERS *pParameters) {
5521 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5522 TRACE("(%p) : pParameters %p\n", This, pParameters);
5524 *pParameters = This->createParms;
5528 static void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST WINED3DGAMMARAMP* pRamp) {
5529 IWineD3DSwapChain *swapchain;
5530 HRESULT hrc = WINED3D_OK;
5532 TRACE("Relaying to swapchain\n");
5534 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5535 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (WINED3DGAMMARAMP *)pRamp);
5536 IWineD3DSwapChain_Release(swapchain);
5541 static void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, WINED3DGAMMARAMP* pRamp) {
5542 IWineD3DSwapChain *swapchain;
5543 HRESULT hrc = WINED3D_OK;
5545 TRACE("Relaying to swapchain\n");
5547 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == WINED3D_OK) {
5548 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5549 IWineD3DSwapChain_Release(swapchain);
5555 /** ********************************************************
5556 * Notification functions
5557 ** ********************************************************/
5558 /** This function must be called in the release of a resource when ref == 0,
5559 * the contents of resource must still be correct,
5560 * any handels to other resource held by the caller must be closed
5561 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5562 *****************************************************/
5563 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5564 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5565 ResourceList* resourceList;
5567 TRACE("(%p) : resource %p\n", This, resource);
5569 EnterCriticalSection(&resourceStoreCriticalSection);
5571 /* add a new texture to the frot of the linked list */
5572 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5573 resourceList->resource = resource;
5575 /* Get the old head */
5576 resourceList->next = This->resources;
5578 This->resources = resourceList;
5579 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5582 LeaveCriticalSection(&resourceStoreCriticalSection);
5587 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5589 ResourceList* resourceList = NULL;
5590 ResourceList* previousResourceList = NULL;
5592 TRACE("(%p) : resource %p\n", This, resource);
5595 EnterCriticalSection(&resourceStoreCriticalSection);
5597 resourceList = This->resources;
5599 while (resourceList != NULL) {
5600 if(resourceList->resource == resource) break;
5601 previousResourceList = resourceList;
5602 resourceList = resourceList->next;
5605 if (resourceList == NULL) {
5606 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5608 LeaveCriticalSection(&resourceStoreCriticalSection);
5612 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5614 /* make sure we don't leave a hole in the list */
5615 if (previousResourceList != NULL) {
5616 previousResourceList->next = resourceList->next;
5618 This->resources = resourceList->next;
5622 LeaveCriticalSection(&resourceStoreCriticalSection);
5628 static void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5629 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5632 TRACE("(%p) : resource %p\n", This, resource);
5633 switch(IWineD3DResource_GetType(resource)){
5634 case WINED3DRTYPE_SURFACE:
5635 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5637 case WINED3DRTYPE_TEXTURE:
5638 case WINED3DRTYPE_CUBETEXTURE:
5639 case WINED3DRTYPE_VOLUMETEXTURE:
5640 for (counter = 0; counter < GL_LIMITS(sampler_stages); counter++) {
5641 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5642 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5643 This->stateBlock->textures[counter] = NULL;
5645 if (This->updateStateBlock != This->stateBlock ){
5646 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5647 WARN("Texture being released is still by a stateblock, Stage = %u Texture = %p\n", counter, resource);
5648 This->updateStateBlock->textures[counter] = NULL;
5653 case WINED3DRTYPE_VOLUME:
5654 /* TODO: nothing really? */
5656 case WINED3DRTYPE_VERTEXBUFFER:
5657 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5660 TRACE("Cleaning up stream pointers\n");
5662 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5663 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5664 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5666 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5667 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5668 FIXME("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5669 This->updateStateBlock->streamSource[streamNumber] = 0;
5670 /* Set changed flag? */
5673 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) */
5674 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5675 TRACE("Vertex buffer released while bound to a state block, stream %d\n", streamNumber);
5676 This->stateBlock->streamSource[streamNumber] = 0;
5679 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5680 else { /* This shouldn't happen */
5681 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5688 case WINED3DRTYPE_INDEXBUFFER:
5689 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5690 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5691 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5692 This->updateStateBlock->pIndexData = NULL;
5695 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5696 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5697 This->stateBlock->pIndexData = NULL;
5703 FIXME("(%p) unknown resource type %p %u\n", This, resource, IWineD3DResource_GetType(resource));
5708 /* Remove the resoruce from the resourceStore */
5709 IWineD3DDeviceImpl_RemoveResource(iface, resource);
5711 TRACE("Resource released\n");
5715 /**********************************************************
5716 * IWineD3DDevice VTbl follows
5717 **********************************************************/
5719 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
5721 /*** IUnknown methods ***/
5722 IWineD3DDeviceImpl_QueryInterface,
5723 IWineD3DDeviceImpl_AddRef,
5724 IWineD3DDeviceImpl_Release,
5725 /*** IWineD3DDevice methods ***/
5726 IWineD3DDeviceImpl_GetParent,
5727 /*** Creation methods**/
5728 IWineD3DDeviceImpl_CreateVertexBuffer,
5729 IWineD3DDeviceImpl_CreateIndexBuffer,
5730 IWineD3DDeviceImpl_CreateStateBlock,
5731 IWineD3DDeviceImpl_CreateSurface,
5732 IWineD3DDeviceImpl_CreateTexture,
5733 IWineD3DDeviceImpl_CreateVolumeTexture,
5734 IWineD3DDeviceImpl_CreateVolume,
5735 IWineD3DDeviceImpl_CreateCubeTexture,
5736 IWineD3DDeviceImpl_CreateQuery,
5737 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
5738 IWineD3DDeviceImpl_CreateVertexDeclaration,
5739 IWineD3DDeviceImpl_CreateVertexShader,
5740 IWineD3DDeviceImpl_CreatePixelShader,
5741 IWineD3DDeviceImpl_CreatePalette,
5742 /*** Odd functions **/
5743 IWineD3DDeviceImpl_Init3D,
5744 IWineD3DDeviceImpl_Uninit3D,
5745 IWineD3DDeviceImpl_SetFullscreen,
5746 IWineD3DDeviceImpl_EvictManagedResources,
5747 IWineD3DDeviceImpl_GetAvailableTextureMem,
5748 IWineD3DDeviceImpl_GetBackBuffer,
5749 IWineD3DDeviceImpl_GetCreationParameters,
5750 IWineD3DDeviceImpl_GetDeviceCaps,
5751 IWineD3DDeviceImpl_GetDirect3D,
5752 IWineD3DDeviceImpl_GetDisplayMode,
5753 IWineD3DDeviceImpl_SetDisplayMode,
5754 IWineD3DDeviceImpl_GetHWND,
5755 IWineD3DDeviceImpl_SetHWND,
5756 IWineD3DDeviceImpl_GetNumberOfSwapChains,
5757 IWineD3DDeviceImpl_GetRasterStatus,
5758 IWineD3DDeviceImpl_GetSwapChain,
5759 IWineD3DDeviceImpl_Reset,
5760 IWineD3DDeviceImpl_SetDialogBoxMode,
5761 IWineD3DDeviceImpl_SetCursorProperties,
5762 IWineD3DDeviceImpl_SetCursorPosition,
5763 IWineD3DDeviceImpl_ShowCursor,
5764 IWineD3DDeviceImpl_TestCooperativeLevel,
5765 /*** Getters and setters **/
5766 IWineD3DDeviceImpl_SetClipPlane,
5767 IWineD3DDeviceImpl_GetClipPlane,
5768 IWineD3DDeviceImpl_SetClipStatus,
5769 IWineD3DDeviceImpl_GetClipStatus,
5770 IWineD3DDeviceImpl_SetCurrentTexturePalette,
5771 IWineD3DDeviceImpl_GetCurrentTexturePalette,
5772 IWineD3DDeviceImpl_SetDepthStencilSurface,
5773 IWineD3DDeviceImpl_GetDepthStencilSurface,
5774 IWineD3DDeviceImpl_SetFVF,
5775 IWineD3DDeviceImpl_GetFVF,
5776 IWineD3DDeviceImpl_SetGammaRamp,
5777 IWineD3DDeviceImpl_GetGammaRamp,
5778 IWineD3DDeviceImpl_SetIndices,
5779 IWineD3DDeviceImpl_GetIndices,
5780 IWineD3DDeviceImpl_SetBasevertexIndex,
5781 IWineD3DDeviceImpl_SetLight,
5782 IWineD3DDeviceImpl_GetLight,
5783 IWineD3DDeviceImpl_SetLightEnable,
5784 IWineD3DDeviceImpl_GetLightEnable,
5785 IWineD3DDeviceImpl_SetMaterial,
5786 IWineD3DDeviceImpl_GetMaterial,
5787 IWineD3DDeviceImpl_SetNPatchMode,
5788 IWineD3DDeviceImpl_GetNPatchMode,
5789 IWineD3DDeviceImpl_SetPaletteEntries,
5790 IWineD3DDeviceImpl_GetPaletteEntries,
5791 IWineD3DDeviceImpl_SetPixelShader,
5792 IWineD3DDeviceImpl_GetPixelShader,
5793 IWineD3DDeviceImpl_SetPixelShaderConstantB,
5794 IWineD3DDeviceImpl_GetPixelShaderConstantB,
5795 IWineD3DDeviceImpl_SetPixelShaderConstantI,
5796 IWineD3DDeviceImpl_GetPixelShaderConstantI,
5797 IWineD3DDeviceImpl_SetPixelShaderConstantF,
5798 IWineD3DDeviceImpl_GetPixelShaderConstantF,
5799 IWineD3DDeviceImpl_SetRenderState,
5800 IWineD3DDeviceImpl_GetRenderState,
5801 IWineD3DDeviceImpl_SetRenderTarget,
5802 IWineD3DDeviceImpl_GetRenderTarget,
5803 IWineD3DDeviceImpl_SetFrontBackBuffers,
5804 IWineD3DDeviceImpl_SetSamplerState,
5805 IWineD3DDeviceImpl_GetSamplerState,
5806 IWineD3DDeviceImpl_SetScissorRect,
5807 IWineD3DDeviceImpl_GetScissorRect,
5808 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
5809 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
5810 IWineD3DDeviceImpl_SetStreamSource,
5811 IWineD3DDeviceImpl_GetStreamSource,
5812 IWineD3DDeviceImpl_SetStreamSourceFreq,
5813 IWineD3DDeviceImpl_GetStreamSourceFreq,
5814 IWineD3DDeviceImpl_SetTexture,
5815 IWineD3DDeviceImpl_GetTexture,
5816 IWineD3DDeviceImpl_SetTextureStageState,
5817 IWineD3DDeviceImpl_GetTextureStageState,
5818 IWineD3DDeviceImpl_SetTransform,
5819 IWineD3DDeviceImpl_GetTransform,
5820 IWineD3DDeviceImpl_SetVertexDeclaration,
5821 IWineD3DDeviceImpl_GetVertexDeclaration,
5822 IWineD3DDeviceImpl_SetVertexShader,
5823 IWineD3DDeviceImpl_GetVertexShader,
5824 IWineD3DDeviceImpl_SetVertexShaderConstantB,
5825 IWineD3DDeviceImpl_GetVertexShaderConstantB,
5826 IWineD3DDeviceImpl_SetVertexShaderConstantI,
5827 IWineD3DDeviceImpl_GetVertexShaderConstantI,
5828 IWineD3DDeviceImpl_SetVertexShaderConstantF,
5829 IWineD3DDeviceImpl_GetVertexShaderConstantF,
5830 IWineD3DDeviceImpl_SetViewport,
5831 IWineD3DDeviceImpl_GetViewport,
5832 IWineD3DDeviceImpl_MultiplyTransform,
5833 IWineD3DDeviceImpl_ValidateDevice,
5834 IWineD3DDeviceImpl_ProcessVertices,
5835 /*** State block ***/
5836 IWineD3DDeviceImpl_BeginStateBlock,
5837 IWineD3DDeviceImpl_EndStateBlock,
5838 /*** Scene management ***/
5839 IWineD3DDeviceImpl_BeginScene,
5840 IWineD3DDeviceImpl_EndScene,
5841 IWineD3DDeviceImpl_Present,
5842 IWineD3DDeviceImpl_Clear,
5844 IWineD3DDeviceImpl_DrawPrimitive,
5845 IWineD3DDeviceImpl_DrawIndexedPrimitive,
5846 IWineD3DDeviceImpl_DrawPrimitiveUP,
5847 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
5848 IWineD3DDeviceImpl_DrawPrimitiveStrided,
5849 IWineD3DDeviceImpl_DrawRectPatch,
5850 IWineD3DDeviceImpl_DrawTriPatch,
5851 IWineD3DDeviceImpl_DeletePatch,
5852 IWineD3DDeviceImpl_ColorFill,
5853 IWineD3DDeviceImpl_UpdateTexture,
5854 IWineD3DDeviceImpl_UpdateSurface,
5855 IWineD3DDeviceImpl_GetFrontBufferData,
5856 /*** object tracking ***/
5857 IWineD3DDeviceImpl_ResourceReleased
5861 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
5862 WINED3DRS_ALPHABLENDENABLE ,
5863 WINED3DRS_ALPHAFUNC ,
5864 WINED3DRS_ALPHAREF ,
5865 WINED3DRS_ALPHATESTENABLE ,
5867 WINED3DRS_COLORWRITEENABLE ,
5868 WINED3DRS_DESTBLEND ,
5869 WINED3DRS_DITHERENABLE ,
5870 WINED3DRS_FILLMODE ,
5871 WINED3DRS_FOGDENSITY ,
5873 WINED3DRS_FOGSTART ,
5874 WINED3DRS_LASTPIXEL ,
5875 WINED3DRS_SHADEMODE ,
5876 WINED3DRS_SRCBLEND ,
5877 WINED3DRS_STENCILENABLE ,
5878 WINED3DRS_STENCILFAIL ,
5879 WINED3DRS_STENCILFUNC ,
5880 WINED3DRS_STENCILMASK ,
5881 WINED3DRS_STENCILPASS ,
5882 WINED3DRS_STENCILREF ,
5883 WINED3DRS_STENCILWRITEMASK ,
5884 WINED3DRS_STENCILZFAIL ,
5885 WINED3DRS_TEXTUREFACTOR ,
5896 WINED3DRS_ZWRITEENABLE
5899 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
5900 WINED3DTSS_ADDRESSW ,
5901 WINED3DTSS_ALPHAARG0 ,
5902 WINED3DTSS_ALPHAARG1 ,
5903 WINED3DTSS_ALPHAARG2 ,
5904 WINED3DTSS_ALPHAOP ,
5905 WINED3DTSS_BUMPENVLOFFSET ,
5906 WINED3DTSS_BUMPENVLSCALE ,
5907 WINED3DTSS_BUMPENVMAT00 ,
5908 WINED3DTSS_BUMPENVMAT01 ,
5909 WINED3DTSS_BUMPENVMAT10 ,
5910 WINED3DTSS_BUMPENVMAT11 ,
5911 WINED3DTSS_COLORARG0 ,
5912 WINED3DTSS_COLORARG1 ,
5913 WINED3DTSS_COLORARG2 ,
5914 WINED3DTSS_COLOROP ,
5915 WINED3DTSS_RESULTARG ,
5916 WINED3DTSS_TEXCOORDINDEX ,
5917 WINED3DTSS_TEXTURETRANSFORMFLAGS
5920 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
5921 WINED3DSAMP_ADDRESSU ,
5922 WINED3DSAMP_ADDRESSV ,
5923 WINED3DSAMP_ADDRESSW ,
5924 WINED3DSAMP_BORDERCOLOR ,
5925 WINED3DSAMP_MAGFILTER ,
5926 WINED3DSAMP_MINFILTER ,
5927 WINED3DSAMP_MIPFILTER ,
5928 WINED3DSAMP_MIPMAPLODBIAS ,
5929 WINED3DSAMP_MAXMIPLEVEL ,
5930 WINED3DSAMP_MAXANISOTROPY ,
5931 WINED3DSAMP_SRGBTEXTURE ,
5932 WINED3DSAMP_ELEMENTINDEX
5935 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
5937 WINED3DRS_AMBIENTMATERIALSOURCE ,
5938 WINED3DRS_CLIPPING ,
5939 WINED3DRS_CLIPPLANEENABLE ,
5940 WINED3DRS_COLORVERTEX ,
5941 WINED3DRS_DIFFUSEMATERIALSOURCE ,
5942 WINED3DRS_EMISSIVEMATERIALSOURCE ,
5943 WINED3DRS_FOGDENSITY ,
5945 WINED3DRS_FOGSTART ,
5946 WINED3DRS_FOGTABLEMODE ,
5947 WINED3DRS_FOGVERTEXMODE ,
5948 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
5949 WINED3DRS_LIGHTING ,
5950 WINED3DRS_LOCALVIEWER ,
5951 WINED3DRS_MULTISAMPLEANTIALIAS ,
5952 WINED3DRS_MULTISAMPLEMASK ,
5953 WINED3DRS_NORMALIZENORMALS ,
5954 WINED3DRS_PATCHEDGESTYLE ,
5955 WINED3DRS_POINTSCALE_A ,
5956 WINED3DRS_POINTSCALE_B ,
5957 WINED3DRS_POINTSCALE_C ,
5958 WINED3DRS_POINTSCALEENABLE ,
5959 WINED3DRS_POINTSIZE ,
5960 WINED3DRS_POINTSIZE_MAX ,
5961 WINED3DRS_POINTSIZE_MIN ,
5962 WINED3DRS_POINTSPRITEENABLE ,
5963 WINED3DRS_RANGEFOGENABLE ,
5964 WINED3DRS_SPECULARMATERIALSOURCE ,
5965 WINED3DRS_TWEENFACTOR ,
5966 WINED3DRS_VERTEXBLEND
5969 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
5970 WINED3DTSS_TEXCOORDINDEX ,
5971 WINED3DTSS_TEXTURETRANSFORMFLAGS
5974 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
5975 WINED3DSAMP_DMAPOFFSET
5978 void IWineD3DDeviceImpl_MarkStateDirty(IWineD3DDeviceImpl *This, DWORD state) {
5979 DWORD rep = StateTable[state].representative;
5983 WineD3DContext *context;
5986 for(i = 0; i < This->numContexts; i++) {
5987 context = This->contexts[i];
5988 if(isStateDirty(context, rep)) continue;
5990 context->dirtyArray[context->numDirtyEntries++] = rep;
5993 context->isStateDirty[idx] |= (1 << shift);