2 * IWineD3DDevice implementation
4 * Copyright 2002-2005 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
29 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
30 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
31 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
33 /* x11drv GDI escapes */
34 #define X11DRV_ESCAPE 6789
35 enum x11drv_escape_codes
37 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
38 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
39 X11DRV_GET_FONT, /* get current X font for a DC */
42 /* retrieve the X display to use on a given DC */
43 inline static Display *get_display( HDC hdc )
46 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
48 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
49 sizeof(display), (LPSTR)&display )) display = NULL;
53 /* Memory tracking and object counting */
54 static unsigned int emulated_textureram = 64*1024*1024;
56 /* TODO: setup some flags in the regestry to enable, disable pbuffer support */
57 /* enable pbuffer support for offscreen textures */
58 BOOL pbuffer_support = TRUE;
59 /* allocate one pbuffer per surface */
60 BOOL pbuffer_per_surface = FALSE;
62 /* static function declarations */
63 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource);
67 #define D3DMEMCHECK(object, ppResult) if(NULL == object) { *ppResult = NULL; WARN("Out of memory\n"); return D3DERR_OUTOFVIDEOMEMORY;}
69 #define D3DCREATEOBJECTINSTANCE(object, type) { \
70 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
71 D3DMEMCHECK(object, pp##type); \
72 object->lpVtbl = &IWineD3D##type##_Vtbl; \
73 object->wineD3DDevice = This; \
74 object->parent = parent; \
76 *pp##type = (IWineD3D##type *) object; \
79 #define D3DCREATERESOURCEOBJECTINSTANCE(object, type, d3dtype, _size){ \
80 object=HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3D##type##Impl)); \
81 D3DMEMCHECK(object, pp##type); \
82 object->lpVtbl = &IWineD3D##type##_Vtbl; \
83 object->resource.wineD3DDevice = This; \
84 object->resource.parent = parent; \
85 object->resource.resourceType = d3dtype; \
86 object->resource.ref = 1; \
87 object->resource.pool = Pool; \
88 object->resource.format = Format; \
89 object->resource.usage = Usage; \
90 object->resource.size = _size; \
91 /* Check that we have enough video ram left */ \
92 if (Pool == D3DPOOL_DEFAULT) { \
93 if (IWineD3DDevice_GetAvailableTextureMem(iface) <= _size) { \
94 WARN("Out of 'bogus' video memory\n"); \
95 HeapFree(GetProcessHeap(),0,object); \
97 return D3DERR_OUTOFVIDEOMEMORY; \
99 globalChangeGlRam(_size); \
101 object->resource.allocatedMemory = (0 == _size ? NULL : Pool == D3DPOOL_DEFAULT ? NULL : HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, _size)); \
102 if (object->resource.allocatedMemory == NULL && _size != 0 && Pool != D3DPOOL_DEFAULT) { \
103 FIXME("Out of memory!\n"); \
104 HeapFree(GetProcessHeap(), 0, object); \
106 return D3DERR_OUTOFVIDEOMEMORY; \
108 *pp##type = (IWineD3D##type *) object; \
109 IWineD3DDeviceImpl_AddResource(iface, (IWineD3DResource *)object) ;\
110 TRACE("(%p) : Created resource %p\n", This, object); \
113 #define D3DINITILIZEBASETEXTURE(_basetexture) { \
114 _basetexture.levels = Levels; \
115 _basetexture.filterType = (Usage & D3DUSAGE_AUTOGENMIPMAP) ? D3DTEXF_LINEAR : D3DTEXF_NONE; \
116 _basetexture.LOD = 0; \
117 _basetexture.dirty = TRUE; \
120 /**********************************************************
121 * Global variable / Constants follow
122 **********************************************************/
123 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
125 /**********************************************************
126 * Utility functions follow
127 **********************************************************/
128 /* Convert the D3DLIGHT properties into equivalent gl lights */
129 static void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
132 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
133 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
135 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
136 glMatrixMode(GL_MODELVIEW);
138 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
141 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
142 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
143 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
144 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
145 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
146 checkGLcall("glLightfv");
149 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
150 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
151 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
152 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
153 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
154 checkGLcall("glLightfv");
157 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
158 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
159 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
160 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
161 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
162 checkGLcall("glLightfv");
164 /* Attenuation - Are these right? guessing... */
165 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
166 checkGLcall("glLightf");
167 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
168 checkGLcall("glLightf");
170 if ((lightInfo->OriginalParms.Range * lightInfo->OriginalParms.Range) != 0 ) {
171 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
173 quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
176 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
177 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
178 checkGLcall("glLightf");
180 switch (lightInfo->OriginalParms.Type) {
183 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
184 checkGLcall("glLightfv");
185 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
186 checkGLcall("glLightf");
192 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
193 checkGLcall("glLightfv");
195 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
196 checkGLcall("glLightfv");
197 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
198 checkGLcall("glLightf");
199 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
200 checkGLcall("glLightf");
204 case D3DLIGHT_DIRECTIONAL:
206 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
207 checkGLcall("glLightfv");
208 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
209 checkGLcall("glLightf");
210 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
211 checkGLcall("glLightf");
215 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
218 /* Restore the modelview matrix */
222 /* Apply the current values to the specified texture stage */
223 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
224 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
227 BOOL changeTexture = TRUE;
229 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
230 for (i = 1; i < WINED3D_HIGHEST_TEXTURE_STATE; i++) {
235 /* Performance: For texture states where multiples effect the outcome, only bother
236 applying the last one as it will pick up all the other values */
237 case WINED3DTSS_COLORARG0: /* Will be picked up when setting color op */
238 case WINED3DTSS_COLORARG1: /* Will be picked up when setting color op */
239 case WINED3DTSS_COLORARG2: /* Will be picked up when setting color op */
240 case WINED3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
241 case WINED3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
242 case WINED3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
246 /* Performance: If the texture states only impact settings for the texture unit
247 (compared to the texture object) then there is no need to reapply them. The
248 only time they need applying is the first time, since we cheat and put the
249 values into the stateblock without applying.
250 Per-texture unit: texture function (eg. combine), ops and args
252 texture generation settings
253 Note: Due to some special conditions there may be a need to do particular ones
254 of these, which is what the Flags allows */
255 case WINED3DTSS_COLOROP:
256 case WINED3DTSS_TEXCOORDINDEX:
257 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
260 case WINED3DTSS_ALPHAOP:
261 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
269 /* Performance: Only change to this texture if we have to */
271 /* Make appropriate texture active */
272 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
273 GLACTIVETEXTURE(Stage);
274 } else if (Stage > 0) {
275 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
277 changeTexture = FALSE;
280 /* Now apply the change */
281 IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
285 /* apply the sampler states to the texture */
286 for (i = 1; i <= WINED3D_HIGHEST_SAMPLER_STATE;i++) {
287 IWineD3DDevice_SetSamplerState(iface, Stage, i, This->stateBlock->samplerState[Stage][i]);
290 /* Note the D3DRS value applies to all textures, but GL has one
291 * per texture, so apply it now ready to be used!
293 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[WINED3DRS_TEXTUREFACTOR], col);
294 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
295 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
297 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
300 /**********************************************************
301 * IUnknown parts follows
302 **********************************************************/
304 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
306 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
307 /* FIXME: This needs to extend an IWineD3DBaseObject */
309 TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
310 if (IsEqualGUID(riid, &IID_IUnknown)
311 || IsEqualGUID(riid, &IID_IWineD3DDevice)) {
312 IUnknown_AddRef(iface);
317 return E_NOINTERFACE;
320 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
321 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
322 ULONG refCount = InterlockedIncrement(&This->ref);
324 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
328 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
329 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
330 ULONG refCount = InterlockedDecrement(&This->ref);
332 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
335 /* TODO: Clean up all the surfaces and textures! */
336 /* FIXME: Create targets and state blocks in d3d8 */
337 if (((IWineD3DImpl *)This->wineD3D)->dxVersion > 8) { /*We don't create a state block in d3d8 yet*/
338 /* NOTE: You must release the parent if the object was created via a callback
339 ** ***************************/
340 IUnknown* swapChainParent;
342 /* NOTE: Don't release swapchain 0 here, it's 'special' */
343 SwapChainList *nextSwapchain = This->swapchains;
344 if (nextSwapchain != NULL) {
345 nextSwapchain = nextSwapchain->next;
347 WARN("Expected to find the implicite swapchain\n");
350 /* release all the other swapchains */
351 while (nextSwapchain != NULL) {
352 SwapChainList *prevSwapchain = nextSwapchain;
353 nextSwapchain = nextSwapchain->next;
354 IWineD3DSwapChain_Release(prevSwapchain->swapchain);
355 /* NOTE: no need to free the list element, it will be done by the release callback
356 HeapFree(GetProcessHeap(), 0, prevSwapchain); */
359 if (This->stateBlock != NULL) {
360 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
363 if (This->swapchains != NULL) {
364 /* Swapchain 0 is special because it's created in startup with a hanging parent, so we have to release it's parent now */
365 IWineD3DSwapChain_GetParent(This->swapchains->swapchain, &swapChainParent);
366 IUnknown_Release(swapChainParent); /* once for the get parent */
367 if (IUnknown_Release(swapChainParent) > 0) { /* the second time for when it was created */
368 FIXME("(%p) Something's still holding the implicite swapchain\n", This);
373 IWineD3D_Release(This->wineD3D);
374 HeapFree(GetProcessHeap(), 0, This);
379 /**********************************************************
380 * IWineD3DDevice implementation follows
381 **********************************************************/
382 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
383 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
384 *pParent = This->parent;
385 IUnknown_AddRef(This->parent);
389 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
390 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
392 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
393 IWineD3DVertexBufferImpl *object;
394 WINED3DFORMAT Format = WINED3DFMT_VERTEXDATA; /* Dummy format for now */
395 D3DCREATERESOURCEOBJECTINSTANCE(object, VertexBuffer, D3DRTYPE_VERTEXBUFFER, Size)
398 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
399 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->resource.size);
403 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->resource.allocatedMemory, object);
404 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
409 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
410 WINED3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
411 HANDLE *sharedHandle, IUnknown *parent) {
412 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
413 IWineD3DIndexBufferImpl *object;
414 TRACE("(%p) Creating index buffer\n", This);
416 /* Allocate the storage for the device */
417 D3DCREATERESOURCEOBJECTINSTANCE(object,IndexBuffer,D3DRTYPE_INDEXBUFFER, Length)
420 if (Pool == D3DPOOL_DEFAULT ) { /* Allocate some system memory for now */
421 object->resource.allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,object->resource.size);
424 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
425 debug_d3dformat(Format), Pool, object, object->resource.allocatedMemory);
426 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
431 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, WINED3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
433 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
434 IWineD3DStateBlockImpl *object;
437 D3DCREATEOBJECTINSTANCE(object, StateBlock)
438 object->blockType = Type;
440 /* Special case - Used during initialization to produce a placeholder stateblock
441 so other functions called can update a state block */
442 if (Type == WINED3DSBT_INIT) {
443 /* Don't bother increasing the reference count otherwise a device will never
444 be freed due to circular dependencies */
448 /* Otherwise, might as well set the whole state block to the appropriate values */
449 IWineD3DDevice_AddRef(iface);
450 /* Otherwise, might as well set the whole state block to the appropriate values */
451 if ( This->stateBlock != NULL) {
452 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
454 memset(object->streamFreq, 1, sizeof(object->streamFreq));
457 /* Reset the ref and type after kludging it */
458 object->wineD3DDevice = This;
460 object->blockType = Type;
462 TRACE("Updating changed flags appropriate for type %d\n", Type);
464 if (Type == WINED3DSBT_ALL) {
465 TRACE("ALL => Pretend everything has changed\n");
466 memset(&object->changed, TRUE, sizeof(This->stateBlock->changed));
467 } else if (Type == WINED3DSBT_PIXELSTATE) {
469 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
470 /* TODO: Pixel Shader Constants */
471 object->changed.pixelShader = TRUE;
472 for (i = 0; i < NUM_SAVEDPIXELSTATES_R; i++) {
473 object->changed.renderState[SavedPixelStates_R[i]] = TRUE;
475 for (j = 0; j < GL_LIMITS(textures); i++) {
476 for (i = 0; i < NUM_SAVEDPIXELSTATES_T; i++) {
477 object->changed.textureState[j][SavedPixelStates_T[i]] = TRUE;
480 /* Setting sampler block changes states */
481 for (j = 0 ; j < GL_LIMITS(samplers); j++) {
482 for (i =0; i < NUM_SAVEDPIXELSTATES_S;i++) {
484 object->changed.samplerState[j][SavedPixelStates_S[i]] = TRUE;
487 } else if (Type == WINED3DSBT_VERTEXSTATE) {
489 memset(&object->changed, FALSE, sizeof(This->stateBlock->changed));
491 /* TODO: Vertex Shader Constants */
492 object->changed.vertexShader = TRUE;
493 for (i = 0; i < NUM_SAVEDVERTEXSTATES_R; i++) {
494 object->changed.renderState[SavedVertexStates_R[i]] = TRUE;
496 for (j = 0; j < GL_LIMITS(textures); i++) {
497 for (i = 0; i < NUM_SAVEDVERTEXSTATES_T; i++) {
498 object->changed.textureState[j][SavedVertexStates_T[i]] = TRUE;
501 /* Setting sampler block changes states */
502 for (j = 0 ; j < GL_LIMITS(samplers); j++) {
503 for (i =0; i < NUM_SAVEDVERTEXSTATES_S;i++) {
504 object->changed.samplerState[j][SavedVertexStates_S[i]] = TRUE;
508 /* Duplicate light chain */
510 PLIGHTINFOEL *src = NULL;
511 PLIGHTINFOEL *dst = NULL;
512 PLIGHTINFOEL *newEl = NULL;
513 src = This->stateBlock->lights;
514 object->lights = NULL;
518 newEl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
519 if (newEl == NULL) return D3DERR_OUTOFVIDEOMEMORY;
520 memcpy(newEl, src, sizeof(PLIGHTINFOEL));
522 newEl->changed = TRUE;
523 newEl->enabledChanged = TRUE;
525 object->lights = newEl;
536 FIXME("Unrecognized state block type %d\n", Type);
539 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, object);
544 /* ************************************
546 [in] Render targets are not lockable unless the application specifies TRUE for Lockable. Note that lockable render targets reduce performance on some graphics hardware.
549 [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
551 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.
553 ******************************** */
555 HRESULT WINAPI IWineD3DDeviceImpl_CreateSurface(IWineD3DDevice *iface, UINT Width, UINT Height, WINED3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IWineD3DSurface **ppSurface,D3DRESOURCETYPE Type, DWORD Usage, D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample ,DWORD MultisampleQuality, HANDLE* pSharedHandle, IUnknown *parent) {
556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
557 IWineD3DSurfaceImpl *object; /*NOTE: impl ref allowed since this is a create function */
558 unsigned int pow2Width, pow2Height;
559 unsigned int Size = 1;
560 TRACE("(%p) Create surface\n",This);
562 /** FIXME: Check ranges on the inputs are valid
565 * [in] Quality level. The valid range is between zero and one less than the level
566 * returned by pQualityLevels used by IDirect3D9::CheckDeviceMultiSampleType.
567 * Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality
568 * values of paired render targets, depth stencil surfaces, and the MultiSample type
570 *******************************/
575 * [in] Set this flag to TRUE to enable z-buffer discarding, and FALSE otherwise.
577 * If this flag is set, the contents of the depth stencil buffer will be
578 * invalid after calling either IDirect3DDevice9::Present or * IDirect3DDevice9::SetDepthStencilSurface
579 * with a different depth surface.
581 *This flag has the same behavior as the constant, D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL, in D3DPRESENTFLAG.
582 ***************************/
584 if(MultisampleQuality < 0) {
585 FIXME("Invalid multisample level %ld \n", MultisampleQuality);
586 return D3DERR_INVALIDCALL; /* TODO: Check that this is the case! */
589 if(MultisampleQuality > 0) {
590 FIXME("MultisampleQuality set to %ld, substituting 0 \n" , MultisampleQuality);
591 MultisampleQuality=0;
594 /* Non-power2 support */
596 /* Find the nearest pow2 match */
597 pow2Width = pow2Height = 1;
598 while (pow2Width < Width) pow2Width <<= 1;
599 while (pow2Height < Height) pow2Height <<= 1;
601 if (pow2Width > Width || pow2Height > Height) {
602 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
603 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
604 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
605 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
606 This, Width, Height);
607 return D3DERR_NOTAVAILABLE;
611 /** TODO: Check against the maximum texture sizes supported by the video card **/
614 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
615 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
617 *********************************/
618 if (Format == WINED3DFMT_DXT1) {
619 /* DXT1 is half byte per pixel */
620 Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4)) >> 1;
622 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
623 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
624 Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4));
626 Size = (Width * D3DFmtGetBpp(This, Format)) * Height;
629 /** Create the and initilise surface resource **/
630 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
631 object->container = (IUnknown*) This;
633 object->currentDesc.Width = Width;
634 object->currentDesc.Height = Height;
635 object->currentDesc.MultiSampleType = MultiSample;
636 object->currentDesc.MultiSampleQuality = MultisampleQuality;
638 /* Setup some glformat defaults */
639 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
640 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
641 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
642 object->glDescription.textureName = 0;
643 object->glDescription.level = Level;
644 object->glDescription.target = GL_TEXTURE_2D;
647 object->pow2Width = pow2Width;
648 object->pow2Height = pow2Height;
649 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
650 object->discard = Discard;
651 object->activeLock = FALSE;
652 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
653 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
655 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
657 /* Precalculated scaling for 'faked' non power of two texture coords */
658 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
659 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
660 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
662 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
664 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
665 * this function is too deap to need to care about things like this.
666 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
667 * ****************************************/
669 case D3DPOOL_SCRATCH:
670 if(Lockable == FALSE)
671 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
672 which are mutually exclusive, setting lockable to true\n");
675 case D3DPOOL_SYSTEMMEM:
676 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
677 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
678 case D3DPOOL_MANAGED:
679 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
680 Usage of DYNAMIC which are mutually exclusive, not doing \
681 anything just telling you.\n");
683 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
684 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
685 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
686 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
689 FIXME("(%p) Unknown pool %d\n", This, Pool);
693 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
694 FIXME("Trying to create a render target that isn't in the default pool\n");
698 object->locked = FALSE;
699 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
701 /* mark the texture as dirty so that it get's loaded first time around*/
702 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
703 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
704 This, Width, Height, Format, debug_d3dformat(Format),
705 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
710 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
711 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
712 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
713 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
715 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
716 IWineD3DTextureImpl *object;
722 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
724 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
725 D3DINITILIZEBASETEXTURE(object->baseTexture);
726 object->width = Width;
727 object->height = Height;
729 /* Calculate levels for mip mapping */
731 TRACE("calculating levels %d\n", object->baseTexture.levels);
732 object->baseTexture.levels++;
735 while (tmpW > 1 && tmpH > 1) {
736 tmpW = max(1, tmpW >> 1);
737 tmpH = max(1, tmpH >> 1);
738 object->baseTexture.levels++;
740 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
743 /* Generate all the surfaces */
746 for (i = 0; i < object->baseTexture.levels; i++)
748 /* use the callback to create the texture surface */
749 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
752 FIXME("Failed to create surface %p \n",object);
754 for(j = 0 ; j < i ; j++) {
755 IWineD3DSurface_Release(object->surfaces[j]);
757 /* heap free object */
758 HeapFree(GetProcessHeap(),0,object);
764 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
765 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
766 /* calculate the next mipmap level */
767 tmpW = max(1, tmpW >> 1);
768 tmpH = max(1, tmpH >> 1);
771 TRACE("(%p) : Created texture %p\n", This, object);
775 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
776 UINT Width, UINT Height, UINT Depth,
777 UINT Levels, DWORD Usage,
778 WINED3DFORMAT Format, D3DPOOL Pool,
779 IWineD3DVolumeTexture** ppVolumeTexture,
780 HANDLE* pSharedHandle, IUnknown *parent,
781 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
783 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
784 IWineD3DVolumeTextureImpl *object;
790 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
791 D3DINITILIZEBASETEXTURE(object->baseTexture);
793 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
794 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
796 object->width = Width;
797 object->height = Height;
798 object->depth = Depth;
800 /* Calculate levels for mip mapping */
802 object->baseTexture.levels++;
806 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
807 tmpW = max(1, tmpW >> 1);
808 tmpH = max(1, tmpH >> 1);
809 tmpD = max(1, tmpD >> 1);
810 object->baseTexture.levels++;
812 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
815 /* Generate all the surfaces */
820 for (i = 0; i < object->baseTexture.levels; i++)
822 /* Create the volume */
823 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
824 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
825 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
827 tmpW = max(1, tmpW >> 1);
828 tmpH = max(1, tmpH >> 1);
829 tmpD = max(1, tmpD >> 1);
832 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
833 TRACE("(%p) : Created volume texture %p\n", This, object);
837 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
838 UINT Width, UINT Height, UINT Depth,
840 WINED3DFORMAT Format, D3DPOOL Pool,
841 IWineD3DVolume** ppVolume,
842 HANDLE* pSharedHandle, IUnknown *parent) {
844 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
845 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
847 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
849 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
850 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
852 object->currentDesc.Width = Width;
853 object->currentDesc.Height = Height;
854 object->currentDesc.Depth = Depth;
855 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
857 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
858 object->lockable = TRUE;
859 object->locked = FALSE;
860 memset(&object->lockedBox, 0, sizeof(D3DBOX));
861 object->dirty = FALSE;
862 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
865 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
866 UINT Levels, DWORD Usage,
867 WINED3DFORMAT Format, D3DPOOL Pool,
868 IWineD3DCubeTexture** ppCubeTexture,
869 HANDLE* pSharedHandle, IUnknown *parent,
870 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
872 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
873 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
878 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
879 D3DINITILIZEBASETEXTURE(object->baseTexture);
881 TRACE("(%p) Create Cube Texture \n", This);
883 object->edgeLength = EdgeLength;
885 /* Calculate levels for mip mapping */
887 object->baseTexture.levels++;
890 tmpW = max(1, tmpW / 2);
891 object->baseTexture.levels++;
893 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
896 /* Generate all the surfaces */
898 for (i = 0; i < object->baseTexture.levels; i++) {
900 /* Create the 6 faces */
901 for (j = 0; j < 6; j++) {
903 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
904 i /* Level */, &object->surfaces[j][i],pSharedHandle);
911 IWineD3DSurface_Release(object->surfaces[j][i]);
915 IWineD3DSurface_Release(object->surfaces[l][j]);
919 FIXME("(%p) Failed to create surface\n",object);
920 HeapFree(GetProcessHeap(),0,object);
921 *ppCubeTexture = NULL;
924 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
925 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
927 tmpW = max(1, tmpW >> 1);
930 TRACE("(%p) : Created Cube Texture %p\n", This, object);
931 *ppCubeTexture = (IWineD3DCubeTexture *) object;
935 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
936 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
937 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
939 if(NULL == ppQuery) {
940 /* Just a check to see if we support this type of query */
941 HRESULT hr = D3DERR_NOTAVAILABLE;
942 /* Lie and say everything is good (we can return ok fake data from a stub) */
944 case WINED3DQUERYTYPE_VCACHE:
945 case WINED3DQUERYTYPE_RESOURCEMANAGER:
946 case WINED3DQUERYTYPE_VERTEXSTATS:
947 case WINED3DQUERYTYPE_EVENT:
948 case WINED3DQUERYTYPE_OCCLUSION:
949 case WINED3DQUERYTYPE_TIMESTAMP:
950 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
951 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
952 case WINED3DQUERYTYPE_PIPELINETIMINGS:
953 case WINED3DQUERYTYPE_INTERFACETIMINGS:
954 case WINED3DQUERYTYPE_VERTEXTIMINGS:
955 case WINED3DQUERYTYPE_PIXELTIMINGS:
956 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
957 case WINED3DQUERYTYPE_CACHEUTILIZATION:
961 FIXME("(%p) Unhandled query type %d\n",This , Type);
963 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
967 D3DCREATEOBJECTINSTANCE(object, Query)
969 object->extendedData = 0;
970 TRACE("(%p) : Created Query %p\n", This, object);
974 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
975 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
977 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
978 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
979 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
982 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
984 XVisualInfo template;
985 GLXContext oldContext;
986 Drawable oldDrawable;
989 TRACE("(%p) : Created Aditional Swap Chain\n", This);
991 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
992 * does a device hold a reference to a swap chain giving them a lifetime of the device
993 * or does the swap chain notify the device of it'd destruction.
994 *******************************/
996 D3DCREATEOBJECTINSTANCE(object, SwapChain)
998 /* Initialize other useful values */
999 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1001 /*********************
1002 * Lookup the window Handle and the relating X window handle
1003 ********************/
1005 /* Setup hwnd we are using, plus which display this equates to */
1006 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1007 if (!object->win_handle) {
1008 object->win_handle = This->createParms.hFocusWindow;
1011 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1012 hDc = GetDC(object->win_handle);
1013 object->display = get_display(hDc);
1014 ReleaseDC(object->win_handle, hDc);
1015 TRACE("Using a display of %p %p \n", object->display, hDc);
1017 if (NULL == object->display || NULL == hDc) {
1018 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1019 return D3DERR_NOTAVAILABLE;
1022 if (object->win == 0) {
1023 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1024 return D3DERR_NOTAVAILABLE;
1027 * Create an opengl context for the display visual
1028 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1029 * use different properties after that point in time. FIXME: How to handle when requested format
1030 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1031 * it chooses is identical to the one already being used!
1032 **********************************/
1034 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1037 /* Create a new context for this swapchain */
1038 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1039 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1040 (or the best possible if none is requested) */
1041 TRACE("Found x visual ID : %ld\n", template.visualid);
1043 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1044 if (NULL == object->visInfo) {
1045 ERR("cannot really get XVisual\n");
1047 return D3DERR_NOTAVAILABLE;
1050 /* Write out some debug info about the visual/s */
1051 TRACE("Using x visual ID : %ld\n", template.visualid);
1052 TRACE(" visual info: %p\n", object->visInfo);
1053 TRACE(" num items : %d\n", num);
1054 for(n = 0;n < num; n++) {
1055 TRACE("=====item=====: %d\n", n + 1);
1056 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1057 TRACE(" screen : %d\n", object->visInfo[n].screen);
1058 TRACE(" depth : %u\n", object->visInfo[n].depth);
1059 TRACE(" class : %d\n", object->visInfo[n].class);
1060 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1061 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1062 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1063 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1064 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1065 /* log some extra glx info */
1066 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1067 TRACE(" gl_aux_buffers : %d\n", value);
1068 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1069 TRACE(" gl_buffer_size : %d\n", value);
1070 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1071 TRACE(" gl_red_size : %d\n", value);
1072 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1073 TRACE(" gl_green_size : %d\n", value);
1074 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1075 TRACE(" gl_blue_size : %d\n", value);
1076 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1077 TRACE(" gl_alpha_size : %d\n", value);
1078 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1079 TRACE(" gl_depth_size : %d\n", value);
1080 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1081 TRACE(" gl_stencil_size : %d\n", value);
1083 /* Now choose a simila visual ID*/
1085 #ifdef USE_CONTEXT_MANAGER
1087 /** TODO: use a context mamager **/
1091 IWineD3DSwapChain *implSwapChain;
1092 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1093 /* The first time around we create the context that is shared with all other swapchains and render targets */
1094 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1095 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1098 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1099 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1100 /* and create a new context with the implicit swapchains context as the shared context */
1101 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1102 IWineD3DSwapChain_Release(implSwapChain);
1107 XFree(object->visInfo);
1108 object->visInfo = NULL;
1110 if (NULL == object->glCtx) {
1111 ERR("cannot create glxContext\n");
1113 return D3DERR_NOTAVAILABLE;
1117 if (object->glCtx == NULL) {
1118 ERR("Error in context creation !\n");
1119 return D3DERR_INVALIDCALL;
1121 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1122 object->win_handle, object->glCtx, object->win, object->visInfo);
1125 /*********************
1126 * Windowed / Fullscreen
1127 *******************/
1130 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1131 * so we should really check to see if their is a fullscreen swapchain already
1132 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1133 **************************************/
1135 if (!*(pPresentationParameters->Windowed)) {
1141 /* Get info on the current display setup */
1142 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1143 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1146 /* Change the display settings */
1147 memset(&devmode, 0, sizeof(DEVMODEW));
1148 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1149 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1150 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1151 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1152 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1153 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1155 /* Make popup window */
1156 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1157 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1158 *(pPresentationParameters->BackBufferWidth),
1159 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1165 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1166 * then the corresponding dimension of the client area of the hDeviceWindow
1167 * (or the focus window, if hDeviceWindow is NULL) is taken.
1168 **********************/
1170 if (*(pPresentationParameters->Windowed) &&
1171 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1172 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1175 GetClientRect(object->win_handle, &Rect);
1177 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1178 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1179 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1181 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1182 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1183 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1187 /*********************
1188 * finish off parameter initialization
1189 *******************/
1191 /* Put the correct figures in the presentation parameters */
1192 TRACE("Coppying accross presentaion paraneters\n");
1193 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1194 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1195 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1196 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1197 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1198 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1199 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1200 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1201 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1202 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1203 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1204 object->presentParms.Flags = *(pPresentationParameters->Flags);
1205 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1206 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1209 /* FIXME: check for any failures */
1210 /*********************
1211 * Create the back, front and stencil buffers
1212 *******************/
1213 TRACE("calling rendertarget CB\n");
1214 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1215 object->presentParms.BackBufferWidth,
1216 object->presentParms.BackBufferHeight,
1217 object->presentParms.BackBufferFormat,
1218 object->presentParms.MultiSampleType,
1219 object->presentParms.MultiSampleQuality,
1220 TRUE /* Lockable */,
1221 &object->frontBuffer,
1222 NULL /* pShared (always null)*/);
1223 if (object->frontBuffer != NULL)
1224 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1225 TRACE("calling rendertarget CB\n");
1226 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1227 object->presentParms.BackBufferWidth,
1228 object->presentParms.BackBufferHeight,
1229 object->presentParms.BackBufferFormat,
1230 object->presentParms.MultiSampleType,
1231 object->presentParms.MultiSampleQuality,
1232 TRUE /* Lockable */,
1233 &object->backBuffer,
1234 NULL /* pShared (always null)*/);
1235 if (object->backBuffer != NULL)
1236 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1238 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1239 if (pPresentationParameters->EnableAutoDepthStencil) {
1240 TRACE("Creating depth stencil buffer\n");
1241 if (This->depthStencilBuffer == NULL ) {
1242 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1243 object->presentParms.BackBufferWidth,
1244 object->presentParms.BackBufferHeight,
1245 object->presentParms.AutoDepthStencilFormat,
1246 object->presentParms.MultiSampleType,
1247 object->presentParms.MultiSampleQuality,
1248 FALSE /* FIXME: Discard */,
1249 &This->depthStencilBuffer,
1250 NULL /* pShared (always null)*/ );
1251 if (This->depthStencilBuffer != NULL)
1252 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1255 /** TODO: A check on width, height and multisample types
1256 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1257 ****************************/
1258 object->wantsDepthStencilBuffer = TRUE;
1260 object->wantsDepthStencilBuffer = FALSE;
1263 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1266 /*********************
1267 * init the default renderTarget management
1268 *******************/
1269 object->drawable = object->win;
1270 object->render_ctx = object->glCtx;
1273 /*********************
1274 * Setup some defaults and clear down the buffers
1275 *******************/
1277 /** save current context and drawable **/
1278 oldContext = glXGetCurrentContext();
1279 oldDrawable = glXGetCurrentDrawable();
1281 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1282 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1283 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1285 checkGLcall("glXMakeCurrent");
1287 TRACE("Setting up the screen\n");
1288 /* Clear the screen */
1289 glClearColor(0.0, 0.0, 0.0, 0.0);
1290 checkGLcall("glClearColor");
1293 glClearStencil(0xffff);
1295 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1296 checkGLcall("glClear");
1298 glColor3f(1.0, 1.0, 1.0);
1299 checkGLcall("glColor3f");
1301 glEnable(GL_LIGHTING);
1302 checkGLcall("glEnable");
1304 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1305 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1307 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1308 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1310 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1311 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1313 /* switch back to the original context (unless it was zero)*/
1314 if (This->swapchains != NULL) {
1315 /** TODO: restore the context and drawable **/
1316 glXMakeCurrent(object->display, oldDrawable, oldContext);
1321 { /* Finally add the swapchain to the end of the devices' swapchain list */
1322 SwapChainList **nextSwapchain;
1323 nextSwapchain = &This->swapchains;
1324 while(*nextSwapchain != NULL) {
1325 nextSwapchain = &((*nextSwapchain)->next);
1327 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1328 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1330 TRACE("Set swapchain to %p\n", object);
1331 } else { /* something went wrong so clean up */
1332 IUnknown* bufferParent;
1333 if (object->frontBuffer) {
1334 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1335 IUnknown_Release(bufferParent); /* once for the get parent */
1336 if(IUnknown_Release(bufferParent) > 0) {
1337 FIXME("(%p) Something's still holding the front buffer\n",This);
1340 if (object->backBuffer) {
1341 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1342 IUnknown_Release(bufferParent); /* once for the get parent */
1343 if(IUnknown_Release(bufferParent) > 0) {
1344 FIXME("(%p) Something's still holding the back buffer\n",This);
1347 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1348 /* Clean up the context */
1349 /* check that we are the current context first (we shouldn't be though!) */
1350 if (object->glCtx != 0) {
1351 if(glXGetCurrentContext() == object->glCtx) {
1352 glXMakeCurrent(object->display, None, NULL);
1354 glXDestroyContext(object->display, object->glCtx);
1356 HeapFree(GetProcessHeap(), 0, object);
1362 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1363 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1364 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1365 unsigned int numberOfSwapChains = 0;
1366 SwapChainList *swapchain;
1368 swapchain = This->swapchains;
1369 /* itterate through the list to get a count */
1370 while (swapchain != NULL) {
1371 swapchain = swapchain->next;
1372 numberOfSwapChains++;
1375 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1376 return numberOfSwapChains;
1379 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1380 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1381 SwapChainList *swapchain;
1382 HRESULT hr = D3DERR_INVALIDCALL;
1383 swapchain = This->swapchains;
1384 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1387 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1388 while (iSwapChain > 0 && swapchain != NULL) {
1389 swapchain = swapchain->next;
1393 if (iSwapChain > 0 || swapchain == NULL) {
1394 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1397 /** TODO: move off to a linkesList implementation **/
1398 *pSwapChain = swapchain->swapchain;
1399 IWineD3DSwapChain_AddRef(*pSwapChain);
1403 TRACE("(%p) returning %p\n", This, *pSwapChain);
1407 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1410 FIXME("(%p) : Stub\n",This);
1416 * Vertex Declaration
1418 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1420 IWineD3DVertexDeclarationImpl *object = NULL;
1421 HRESULT hr = D3D_OK;
1422 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1423 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1426 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1431 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1432 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1433 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1434 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1435 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1436 object->function = pFunction;
1437 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1442 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1443 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1444 FIXME("(%p) : Stub\n", This);
1448 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1449 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1450 *ppD3D= This->wineD3D;
1451 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1452 IWineD3D_AddRef(*ppD3D);
1457 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1458 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1459 * Into the video ram as possible and seeing how many fit
1460 * you can also get the correct initial value from via X and ATI's driver
1461 *******************/
1462 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1463 static BOOL showfixmes = TRUE;
1465 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1466 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1469 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1470 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1471 /* videomemory is simulated videomemory + AGP memory left */
1472 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1480 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1481 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1483 /* Update the current state block */
1484 This->updateStateBlock->fvf = fvf;
1485 This->updateStateBlock->changed.fvf = TRUE;
1486 This->updateStateBlock->set.fvf = TRUE;
1488 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1489 /* clear down the vertex declaration
1490 NOTE: Axis and Allies doesn't work properly otherwise
1491 (may be a stateblock problem though!)
1493 /* No difference if recording or not */
1494 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1499 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1500 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1501 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1502 *pfvf = This->stateBlock->fvf;
1507 * Get / Set Stream Source
1509 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1510 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1511 IWineD3DVertexBuffer *oldSrc;
1513 oldSrc = This->stateBlock->streamSource[StreamNumber];
1514 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1516 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1517 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1518 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1519 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1520 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1522 /* Handle recording of state blocks */
1523 if (This->isRecordingState) {
1524 TRACE("Recording... not performing anything\n");
1528 /* Not recording... */
1529 if (pStreamData != NULL) {
1530 IUnknown *newVertexBufferParent;
1531 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1532 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1534 if (oldSrc != NULL) {
1535 IUnknown *oldVertexBufferParent;
1536 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1537 IUnknown_Release(oldVertexBufferParent);
1538 IUnknown_Release(oldVertexBufferParent);
1544 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1545 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1547 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1548 *pStream = This->stateBlock->streamSource[StreamNumber];
1549 *pStride = This->stateBlock->streamStride[StreamNumber];
1550 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1551 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1555 /*Should be quite easy, just an extension of vertexdata
1557 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1559 The divider is a bit odd though
1561 VertexOffset = StartVertex / Divider * StreamStride +
1562 VertexIndex / Divider * StreamStride + StreamOffset
1565 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1566 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1568 FIXME("(%p) : stub\n", This);
1572 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1573 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1575 FIXME("(%p) : stub\n", This);
1580 * Get / Set & Multiply Transform
1582 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1583 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1585 /* Most of this routine, comments included copied from ddraw tree initially: */
1586 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1588 /* Handle recording of state blocks */
1589 if (This->isRecordingState) {
1590 TRACE("Recording... not performing anything\n");
1591 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1592 This->updateStateBlock->set.transform[d3dts] = TRUE;
1593 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1598 * If the new matrix is the same as the current one,
1599 * we cut off any further processing. this seems to be a reasonable
1600 * optimization because as was noticed, some apps (warcraft3 for example)
1601 * tend towards setting the same matrix repeatedly for some reason.
1603 * From here on we assume that the new matrix is different, wherever it matters.
1605 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1606 TRACE("The app is setting the same matrix over again\n");
1609 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1613 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1614 where ViewMat = Camera space, WorldMat = world space.
1616 In OpenGL, camera and world space is combined into GL_MODELVIEW
1617 matrix. The Projection matrix stay projection matrix.
1620 /* Capture the times we can just ignore the change for now */
1621 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1622 This->modelview_valid = FALSE;
1625 } else if (d3dts == D3DTS_PROJECTION) {
1626 This->proj_valid = FALSE;
1629 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1630 /* Indexed Vertex Blending Matrices 256 -> 511 */
1631 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1632 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1636 /* Now we really are going to have to change a matrix */
1639 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1640 if (d3dts < GL_LIMITS(textures)) {
1641 int tex = d3dts - D3DTS_TEXTURE0;
1642 GLACTIVETEXTURE(tex);
1643 set_texture_matrix((float *)lpmatrix,
1644 This->updateStateBlock->textureState[tex][WINED3DTSS_TEXTURETRANSFORMFLAGS], (This->stateBlock->textureState[tex][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
1647 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1650 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1651 * NOTE: We have to reset the positions even if the light/plane is not currently
1652 * enabled, since the call to enable it will not reset the position.
1653 * NOTE2: Apparently texture transforms do NOT need reapplying
1656 PLIGHTINFOEL *lightChain = NULL;
1657 This->modelview_valid = FALSE;
1658 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1660 glMatrixMode(GL_MODELVIEW);
1661 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1663 glLoadMatrixf((float *)lpmatrix);
1664 checkGLcall("glLoadMatrixf(...)");
1667 lightChain = This->stateBlock->lights;
1668 while (lightChain && lightChain->glIndex != -1) {
1669 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1670 checkGLcall("glLightfv posn");
1671 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1672 checkGLcall("glLightfv dirn");
1673 lightChain = lightChain->next;
1676 /* Reset Clipping Planes if clipping is enabled */
1677 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1678 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1679 checkGLcall("glClipPlane");
1683 } else { /* What was requested!?? */
1684 WARN("invalid matrix specified: %i\n", d3dts);
1687 /* Release lock, all done */
1692 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1693 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1694 TRACE("(%p) : for Transform State %d\n", This, State);
1695 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1699 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1700 D3DMATRIX *mat = NULL;
1703 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1704 * below means it will be recorded in a state block change, but it
1705 * works regardless where it is recorded.
1706 * If this is found to be wrong, change to StateBlock.
1708 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1709 TRACE("(%p) : For state %u\n", This, State);
1711 if (State < HIGHEST_TRANSFORMSTATE)
1713 mat = &This->updateStateBlock->transforms[State];
1715 FIXME("Unhandled transform state!!\n");
1718 /* Copied from ddraw code: */
1719 temp.u.s._11 = (mat->u.s._11 * pMatrix->u.s._11) + (mat->u.s._21 * pMatrix->u.s._12) + (mat->u.s._31 * pMatrix->u.s._13) + (mat->u.s._41 * pMatrix->u.s._14);
1720 temp.u.s._21 = (mat->u.s._11 * pMatrix->u.s._21) + (mat->u.s._21 * pMatrix->u.s._22) + (mat->u.s._31 * pMatrix->u.s._23) + (mat->u.s._41 * pMatrix->u.s._24);
1721 temp.u.s._31 = (mat->u.s._11 * pMatrix->u.s._31) + (mat->u.s._21 * pMatrix->u.s._32) + (mat->u.s._31 * pMatrix->u.s._33) + (mat->u.s._41 * pMatrix->u.s._34);
1722 temp.u.s._41 = (mat->u.s._11 * pMatrix->u.s._41) + (mat->u.s._21 * pMatrix->u.s._42) + (mat->u.s._31 * pMatrix->u.s._43) + (mat->u.s._41 * pMatrix->u.s._44);
1724 temp.u.s._12 = (mat->u.s._12 * pMatrix->u.s._11) + (mat->u.s._22 * pMatrix->u.s._12) + (mat->u.s._32 * pMatrix->u.s._13) + (mat->u.s._42 * pMatrix->u.s._14);
1725 temp.u.s._22 = (mat->u.s._12 * pMatrix->u.s._21) + (mat->u.s._22 * pMatrix->u.s._22) + (mat->u.s._32 * pMatrix->u.s._23) + (mat->u.s._42 * pMatrix->u.s._24);
1726 temp.u.s._32 = (mat->u.s._12 * pMatrix->u.s._31) + (mat->u.s._22 * pMatrix->u.s._32) + (mat->u.s._32 * pMatrix->u.s._33) + (mat->u.s._42 * pMatrix->u.s._34);
1727 temp.u.s._42 = (mat->u.s._12 * pMatrix->u.s._41) + (mat->u.s._22 * pMatrix->u.s._42) + (mat->u.s._32 * pMatrix->u.s._43) + (mat->u.s._42 * pMatrix->u.s._44);
1729 temp.u.s._13 = (mat->u.s._13 * pMatrix->u.s._11) + (mat->u.s._23 * pMatrix->u.s._12) + (mat->u.s._33 * pMatrix->u.s._13) + (mat->u.s._43 * pMatrix->u.s._14);
1730 temp.u.s._23 = (mat->u.s._13 * pMatrix->u.s._21) + (mat->u.s._23 * pMatrix->u.s._22) + (mat->u.s._33 * pMatrix->u.s._23) + (mat->u.s._43 * pMatrix->u.s._24);
1731 temp.u.s._33 = (mat->u.s._13 * pMatrix->u.s._31) + (mat->u.s._23 * pMatrix->u.s._32) + (mat->u.s._33 * pMatrix->u.s._33) + (mat->u.s._43 * pMatrix->u.s._34);
1732 temp.u.s._43 = (mat->u.s._13 * pMatrix->u.s._41) + (mat->u.s._23 * pMatrix->u.s._42) + (mat->u.s._33 * pMatrix->u.s._43) + (mat->u.s._43 * pMatrix->u.s._44);
1734 temp.u.s._14 = (mat->u.s._14 * pMatrix->u.s._11) + (mat->u.s._24 * pMatrix->u.s._12) + (mat->u.s._34 * pMatrix->u.s._13) + (mat->u.s._44 * pMatrix->u.s._14);
1735 temp.u.s._24 = (mat->u.s._14 * pMatrix->u.s._21) + (mat->u.s._24 * pMatrix->u.s._22) + (mat->u.s._34 * pMatrix->u.s._23) + (mat->u.s._44 * pMatrix->u.s._24);
1736 temp.u.s._34 = (mat->u.s._14 * pMatrix->u.s._31) + (mat->u.s._24 * pMatrix->u.s._32) + (mat->u.s._34 * pMatrix->u.s._33) + (mat->u.s._44 * pMatrix->u.s._34);
1737 temp.u.s._44 = (mat->u.s._14 * pMatrix->u.s._41) + (mat->u.s._24 * pMatrix->u.s._42) + (mat->u.s._34 * pMatrix->u.s._43) + (mat->u.s._44 * pMatrix->u.s._44);
1739 /* Apply change via set transform - will reapply to eg. lights this way */
1740 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1746 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1748 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1749 you can reference any indexes you want as long as that number max are enabled at any
1750 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1751 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1752 but when recording, just build a chain pretty much of commands to be replayed. */
1754 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1756 PLIGHTINFOEL *object, *temp;
1758 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1759 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1761 /* If recording state block, just add to end of lights chain */
1762 if (This->isRecordingState) {
1763 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1764 if (NULL == object) {
1765 return D3DERR_OUTOFVIDEOMEMORY;
1767 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1768 object->OriginalIndex = Index;
1769 object->glIndex = -1;
1770 object->changed = TRUE;
1772 /* Add to the END of the chain of lights changes to be replayed */
1773 if (This->updateStateBlock->lights == NULL) {
1774 This->updateStateBlock->lights = object;
1776 temp = This->updateStateBlock->lights;
1777 while (temp->next != NULL) temp=temp->next;
1778 temp->next = object;
1780 TRACE("Recording... not performing anything more\n");
1784 /* Ok, not recording any longer so do real work */
1785 object = This->stateBlock->lights;
1786 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1788 /* If we didn't find it in the list of lights, time to add it */
1789 if (object == NULL) {
1790 PLIGHTINFOEL *insertAt,*prevPos;
1792 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1793 if (NULL == object) {
1794 return D3DERR_OUTOFVIDEOMEMORY;
1796 object->OriginalIndex = Index;
1797 object->glIndex = -1;
1799 /* Add it to the front of list with the idea that lights will be changed as needed
1800 BUT after any lights currently assigned GL indexes */
1801 insertAt = This->stateBlock->lights;
1803 while (insertAt != NULL && insertAt->glIndex != -1) {
1805 insertAt = insertAt->next;
1808 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1809 This->stateBlock->lights = object;
1810 } else if (insertAt == NULL) { /* End of list */
1811 prevPos->next = object;
1812 object->prev = prevPos;
1813 } else { /* Middle of chain */
1814 if (prevPos == NULL) {
1815 This->stateBlock->lights = object;
1817 prevPos->next = object;
1819 object->prev = prevPos;
1820 object->next = insertAt;
1821 insertAt->prev = object;
1825 /* Initialze the object */
1826 TRACE("Light %ld setting to type %d, Diffuse(%f,%f,%f,%f), Specular(%f,%f,%f,%f), Ambient(%f,%f,%f,%f)\n", Index, pLight->Type,
1827 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1828 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1829 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1830 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1831 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1832 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1834 /* Save away the information */
1835 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1837 switch (pLight->Type) {
1838 case D3DLIGHT_POINT:
1840 object->lightPosn[0] = pLight->Position.x;
1841 object->lightPosn[1] = pLight->Position.y;
1842 object->lightPosn[2] = pLight->Position.z;
1843 object->lightPosn[3] = 1.0f;
1844 object->cutoff = 180.0f;
1848 case D3DLIGHT_DIRECTIONAL:
1850 object->lightPosn[0] = -pLight->Direction.x;
1851 object->lightPosn[1] = -pLight->Direction.y;
1852 object->lightPosn[2] = -pLight->Direction.z;
1853 object->lightPosn[3] = 0.0;
1854 object->exponent = 0.0f;
1855 object->cutoff = 180.0f;
1860 object->lightPosn[0] = pLight->Position.x;
1861 object->lightPosn[1] = pLight->Position.y;
1862 object->lightPosn[2] = pLight->Position.z;
1863 object->lightPosn[3] = 1.0;
1866 object->lightDirn[0] = pLight->Direction.x;
1867 object->lightDirn[1] = pLight->Direction.y;
1868 object->lightDirn[2] = pLight->Direction.z;
1869 object->lightDirn[3] = 1.0;
1872 * opengl-ish and d3d-ish spot lights use too different models for the
1873 * light "intensity" as a function of the angle towards the main light direction,
1874 * so we only can approximate very roughly.
1875 * however spot lights are rather rarely used in games (if ever used at all).
1876 * furthermore if still used, probably nobody pays attention to such details.
1878 if (pLight->Falloff == 0) {
1881 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1883 if (rho < 0.0001) rho = 0.0001f;
1884 object->exponent = -0.3/log(cos(rho/2));
1885 object->cutoff = pLight->Phi*90/M_PI;
1891 FIXME("Unrecognized light type %d\n", pLight->Type);
1894 /* Update the live definitions if the light is currently assigned a glIndex */
1895 if (object->glIndex != -1) {
1896 setup_light(iface, object->glIndex, object);
1901 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1902 PLIGHTINFOEL *lightInfo = NULL;
1903 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1904 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1906 /* Locate the light in the live lights */
1907 lightInfo = This->stateBlock->lights;
1908 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1910 if (lightInfo == NULL) {
1911 TRACE("Light information requested but light not defined\n");
1912 return D3DERR_INVALIDCALL;
1915 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1920 * Get / Set Light Enable
1921 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1923 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1924 PLIGHTINFOEL *lightInfo = NULL;
1925 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1926 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1928 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1929 if (This->isRecordingState) {
1930 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1931 if (NULL == lightInfo) {
1932 return D3DERR_OUTOFVIDEOMEMORY;
1934 lightInfo->OriginalIndex = Index;
1935 lightInfo->glIndex = -1;
1936 lightInfo->enabledChanged = TRUE;
1938 /* Add to the END of the chain of lights changes to be replayed */
1939 if (This->updateStateBlock->lights == NULL) {
1940 This->updateStateBlock->lights = lightInfo;
1942 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1943 while (temp->next != NULL) temp=temp->next;
1944 temp->next = lightInfo;
1946 TRACE("Recording... not performing anything more\n");
1950 /* Not recording... So, locate the light in the live lights */
1951 lightInfo = This->stateBlock->lights;
1952 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1954 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1955 if (lightInfo == NULL) {
1956 D3DLIGHT9 lightParms;
1957 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1958 wait until someone confirms it seems to work! */
1959 TRACE("Light enabled requested but light not defined, so defining one!\n");
1960 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1961 lightParms.Diffuse.r = 1.0;
1962 lightParms.Diffuse.g = 1.0;
1963 lightParms.Diffuse.b = 1.0;
1964 lightParms.Diffuse.a = 0.0;
1965 lightParms.Specular.r = 0.0;
1966 lightParms.Specular.g = 0.0;
1967 lightParms.Specular.b = 0.0;
1968 lightParms.Specular.a = 0.0;
1969 lightParms.Ambient.r = 0.0;
1970 lightParms.Ambient.g = 0.0;
1971 lightParms.Ambient.b = 0.0;
1972 lightParms.Ambient.a = 0.0;
1973 lightParms.Position.x = 0.0;
1974 lightParms.Position.y = 0.0;
1975 lightParms.Position.z = 0.0;
1976 lightParms.Direction.x = 0.0;
1977 lightParms.Direction.y = 0.0;
1978 lightParms.Direction.z = 1.0;
1979 lightParms.Range = 0.0;
1980 lightParms.Falloff = 0.0;
1981 lightParms.Attenuation0 = 0.0;
1982 lightParms.Attenuation1 = 0.0;
1983 lightParms.Attenuation2 = 0.0;
1984 lightParms.Theta = 0.0;
1985 lightParms.Phi = 0.0;
1986 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1988 /* Search for it again! Should be fairly quick as near head of list */
1989 lightInfo = This->stateBlock->lights;
1990 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1991 if (lightInfo == NULL) {
1992 FIXME("Adding default lights has failed dismally\n");
1993 return D3DERR_INVALIDCALL;
1997 /* OK, we now have a light... */
1998 if (Enable == FALSE) {
2000 /* If we are disabling it, check it was enabled, and
2001 still only do something if it has assigned a glIndex (which it should have!) */
2002 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2003 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2005 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2006 checkGLcall("glDisable GL_LIGHT0+Index");
2009 TRACE("Nothing to do as light was not enabled\n");
2011 lightInfo->lightEnabled = FALSE;
2014 /* We are enabling it. If it is enabled, it's really simple */
2015 if (lightInfo->lightEnabled) {
2017 TRACE("Nothing to do as light was enabled\n");
2019 /* If it already has a glIndex, it's still simple */
2020 } else if (lightInfo->glIndex != -1) {
2021 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2022 lightInfo->lightEnabled = TRUE;
2024 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2025 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2028 /* Otherwise got to find space - lights are ordered gl indexes first */
2030 PLIGHTINFOEL *bsf = NULL;
2031 PLIGHTINFOEL *pos = This->stateBlock->lights;
2032 PLIGHTINFOEL *prev = NULL;
2036 /* Try to minimize changes as much as possible */
2037 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2039 /* Try to remember which index can be replaced if necessary */
2040 if (bsf==NULL && pos->lightEnabled == FALSE) {
2041 /* Found a light we can replace, save as best replacement */
2045 /* Step to next space */
2051 /* If we have too many active lights, fail the call */
2052 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2053 FIXME("Program requests too many concurrent lights\n");
2054 return D3DERR_INVALIDCALL;
2056 /* If we have allocated all lights, but not all are enabled,
2057 reuse one which is not enabled */
2058 } else if (Index == This->maxConcurrentLights) {
2059 /* use bsf - Simply swap the new light and the BSF one */
2060 PLIGHTINFOEL *bsfNext = bsf->next;
2061 PLIGHTINFOEL *bsfPrev = bsf->prev;
2064 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2065 if (bsf->prev != NULL) {
2066 bsf->prev->next = lightInfo;
2068 This->stateBlock->lights = lightInfo;
2071 /* If not side by side, lots of chains to update */
2072 if (bsf->next != lightInfo) {
2073 lightInfo->prev->next = bsf;
2074 bsf->next->prev = lightInfo;
2075 bsf->next = lightInfo->next;
2076 bsf->prev = lightInfo->prev;
2077 lightInfo->next = bsfNext;
2078 lightInfo->prev = bsfPrev;
2082 bsf->prev = lightInfo;
2083 bsf->next = lightInfo->next;
2084 lightInfo->next = bsf;
2085 lightInfo->prev = bsfPrev;
2090 glIndex = bsf->glIndex;
2092 lightInfo->glIndex = glIndex;
2093 lightInfo->lightEnabled = TRUE;
2095 /* Finally set up the light in gl itself */
2096 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2098 setup_light(iface, glIndex, lightInfo);
2099 glEnable(GL_LIGHT0 + glIndex);
2100 checkGLcall("glEnable GL_LIGHT0 new setup");
2103 /* If we reached the end of the allocated lights, with space in the
2104 gl lights, setup a new light */
2105 } else if (pos->glIndex == -1) {
2107 /* We reached the end of the allocated gl lights, so already
2108 know the index of the next one! */
2110 lightInfo->glIndex = glIndex;
2111 lightInfo->lightEnabled = TRUE;
2113 /* In an ideal world, it's already in the right place */
2114 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2115 /* No need to move it */
2117 /* Remove this light from the list */
2118 lightInfo->prev->next = lightInfo->next;
2119 if (lightInfo->next != NULL) {
2120 lightInfo->next->prev = lightInfo->prev;
2123 /* Add in at appropriate place (inbetween prev and pos) */
2124 lightInfo->prev = prev;
2125 lightInfo->next = pos;
2127 This->stateBlock->lights = lightInfo;
2129 prev->next = lightInfo;
2132 pos->prev = lightInfo;
2136 /* Finally set up the light in gl itself */
2137 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2139 setup_light(iface, glIndex, lightInfo);
2140 glEnable(GL_LIGHT0 + glIndex);
2141 checkGLcall("glEnable GL_LIGHT0 new setup");
2150 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2152 PLIGHTINFOEL *lightInfo = NULL;
2153 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2154 TRACE("(%p) : for idx(%ld)\n", This, Index);
2156 /* Locate the light in the live lights */
2157 lightInfo = This->stateBlock->lights;
2158 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2160 if (lightInfo == NULL) {
2161 TRACE("Light enabled state requested but light not defined\n");
2162 return D3DERR_INVALIDCALL;
2164 *pEnable = lightInfo->lightEnabled;
2169 * Get / Set Clip Planes
2171 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2172 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2173 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2175 /* Validate Index */
2176 if (Index >= GL_LIMITS(clipplanes)) {
2177 TRACE("Application has requested clipplane this device doesn't support\n");
2178 return D3DERR_INVALIDCALL;
2181 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2182 This->updateStateBlock->set.clipplane[Index] = TRUE;
2183 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2184 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2185 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2186 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2188 /* Handle recording of state blocks */
2189 if (This->isRecordingState) {
2190 TRACE("Recording... not performing anything\n");
2198 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2199 glMatrixMode(GL_MODELVIEW);
2201 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2203 TRACE("Clipplane [%f,%f,%f,%f]\n",
2204 This->updateStateBlock->clipplane[Index][0],
2205 This->updateStateBlock->clipplane[Index][1],
2206 This->updateStateBlock->clipplane[Index][2],
2207 This->updateStateBlock->clipplane[Index][3]);
2208 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2209 checkGLcall("glClipPlane");
2217 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2218 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2219 TRACE("(%p) : for idx %ld\n", This, Index);
2221 /* Validate Index */
2222 if (Index >= GL_LIMITS(clipplanes)) {
2223 TRACE("Application has requested clipplane this device doesn't support\n");
2224 return D3DERR_INVALIDCALL;
2227 pPlane[0] = This->stateBlock->clipplane[Index][0];
2228 pPlane[1] = This->stateBlock->clipplane[Index][1];
2229 pPlane[2] = This->stateBlock->clipplane[Index][2];
2230 pPlane[3] = This->stateBlock->clipplane[Index][3];
2235 * Get / Set Clip Plane Status
2236 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2238 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2239 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2240 FIXME("(%p) : stub\n", This);
2241 if (NULL == pClipStatus) {
2242 return D3DERR_INVALIDCALL;
2244 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2245 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2249 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2250 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2251 FIXME("(%p) : stub\n", This);
2252 if (NULL == pClipStatus) {
2253 return D3DERR_INVALIDCALL;
2255 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2256 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2261 * Get / Set Material
2262 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2264 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2265 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2267 This->updateStateBlock->changed.material = TRUE;
2268 This->updateStateBlock->set.material = TRUE;
2269 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2271 /* Handle recording of state blocks */
2272 if (This->isRecordingState) {
2273 TRACE("Recording... not performing anything\n");
2278 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2279 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2280 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2281 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2282 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2284 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2285 checkGLcall("glMaterialfv");
2286 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2287 checkGLcall("glMaterialfv");
2289 /* Only change material color if specular is enabled, otherwise it is set to black */
2290 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2291 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2292 checkGLcall("glMaterialfv");
2294 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2295 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2296 checkGLcall("glMaterialfv");
2298 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2299 checkGLcall("glMaterialfv");
2300 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2301 checkGLcall("glMaterialf");
2307 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2308 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2309 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2310 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2311 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2312 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2313 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2314 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2321 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2322 UINT BaseVertexIndex) {
2323 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2324 IWineD3DIndexBuffer *oldIdxs;
2326 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2327 oldIdxs = This->updateStateBlock->pIndexData;
2329 This->updateStateBlock->changed.indices = TRUE;
2330 This->updateStateBlock->set.indices = TRUE;
2331 This->updateStateBlock->pIndexData = pIndexData;
2332 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2334 /* Handle recording of state blocks */
2335 if (This->isRecordingState) {
2336 TRACE("Recording... not performing anything\n");
2341 IUnknown *indexBufferParent;
2342 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2343 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2346 IUnknown *indexBufferParent;
2347 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2348 IUnknown_Release(indexBufferParent);
2349 IUnknown_Release(indexBufferParent);
2354 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2355 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2357 *ppIndexData = This->stateBlock->pIndexData;
2359 /* up ref count on ppindexdata */
2360 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2361 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2367 * Get / Set Viewports
2369 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2370 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2372 TRACE("(%p)\n", This);
2373 This->updateStateBlock->changed.viewport = TRUE;
2374 This->updateStateBlock->set.viewport = TRUE;
2375 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2377 /* Handle recording of state blocks */
2378 if (This->isRecordingState) {
2379 TRACE("Recording... not performing anything\n");
2385 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2386 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2388 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2389 checkGLcall("glDepthRange");
2390 /* Note: GL requires lower left, DirectX supplies upper left */
2391 /* TODO: replace usage of renderTarget with context management */
2392 glViewport(pViewport->X,
2393 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2394 pViewport->Width, pViewport->Height);
2396 checkGLcall("glViewport");
2404 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2405 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2406 TRACE("(%p)\n", This);
2407 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2412 * Get / Set Render States
2413 * TODO: Verify against dx9 definitions
2415 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2417 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2418 DWORD OldValue = This->stateBlock->renderState[State];
2420 /* Simple way of referring to either a DWORD or a 4 byte float */
2426 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2427 This->updateStateBlock->changed.renderState[State] = TRUE;
2428 This->updateStateBlock->set.renderState[State] = TRUE;
2429 This->updateStateBlock->renderState[State] = Value;
2431 /* Handle recording of state blocks */
2432 if (This->isRecordingState) {
2433 TRACE("Recording... not performing anything\n");
2440 case WINED3DRS_FILLMODE :
2441 switch ((D3DFILLMODE) Value) {
2442 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2443 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2444 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2446 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2448 checkGLcall("glPolygonMode (fillmode)");
2451 case WINED3DRS_LIGHTING :
2453 glEnable(GL_LIGHTING);
2454 checkGLcall("glEnable GL_LIGHTING");
2456 glDisable(GL_LIGHTING);
2457 checkGLcall("glDisable GL_LIGHTING");
2461 case WINED3DRS_ZENABLE :
2462 switch ((D3DZBUFFERTYPE) Value) {
2464 glDisable(GL_DEPTH_TEST);
2465 checkGLcall("glDisable GL_DEPTH_TEST");
2468 glEnable(GL_DEPTH_TEST);
2469 checkGLcall("glEnable GL_DEPTH_TEST");
2472 glEnable(GL_DEPTH_TEST);
2473 checkGLcall("glEnable GL_DEPTH_TEST");
2474 FIXME("W buffer is not well handled\n");
2477 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2481 case WINED3DRS_CULLMODE :
2483 /* If we are culling "back faces with clockwise vertices" then
2484 set front faces to be counter clockwise and enable culling
2486 switch ((D3DCULL) Value) {
2488 glDisable(GL_CULL_FACE);
2489 checkGLcall("glDisable GL_CULL_FACE");
2492 glEnable(GL_CULL_FACE);
2493 checkGLcall("glEnable GL_CULL_FACE");
2494 if (This->renderUpsideDown) {
2496 checkGLcall("glFrontFace GL_CW");
2498 glFrontFace(GL_CCW);
2499 checkGLcall("glFrontFace GL_CCW");
2501 glCullFace(GL_BACK);
2504 glEnable(GL_CULL_FACE);
2505 checkGLcall("glEnable GL_CULL_FACE");
2506 if (This->renderUpsideDown) {
2507 glFrontFace(GL_CCW);
2508 checkGLcall("glFrontFace GL_CCW");
2511 checkGLcall("glFrontFace GL_CW");
2513 glCullFace(GL_BACK);
2516 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2520 case WINED3DRS_SHADEMODE :
2521 switch ((D3DSHADEMODE) Value) {
2523 glShadeModel(GL_FLAT);
2524 checkGLcall("glShadeModel");
2526 case D3DSHADE_GOURAUD:
2527 glShadeModel(GL_SMOOTH);
2528 checkGLcall("glShadeModel");
2530 case D3DSHADE_PHONG:
2531 FIXME("D3DSHADE_PHONG isn't supported?\n");
2534 return D3DERR_INVALIDCALL;
2536 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2540 case WINED3DRS_DITHERENABLE :
2542 glEnable(GL_DITHER);
2543 checkGLcall("glEnable GL_DITHER");
2545 glDisable(GL_DITHER);
2546 checkGLcall("glDisable GL_DITHER");
2550 case WINED3DRS_ZWRITEENABLE :
2553 checkGLcall("glDepthMask");
2556 checkGLcall("glDepthMask");
2560 case WINED3DRS_ZFUNC :
2562 int glParm = GL_LESS;
2564 switch ((D3DCMPFUNC) Value) {
2565 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2566 case D3DCMP_LESS: glParm=GL_LESS; break;
2567 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2568 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2569 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2570 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2571 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2572 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2574 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2576 glDepthFunc(glParm);
2577 checkGLcall("glDepthFunc");
2581 case WINED3DRS_AMBIENT :
2584 D3DCOLORTOGLFLOAT4(Value, col);
2585 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2586 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2587 checkGLcall("glLightModel for MODEL_AMBIENT");
2592 case WINED3DRS_ALPHABLENDENABLE :
2595 checkGLcall("glEnable GL_BLEND");
2597 glDisable(GL_BLEND);
2598 checkGLcall("glDisable GL_BLEND");
2602 case WINED3DRS_SRCBLEND :
2603 case WINED3DRS_DESTBLEND :
2605 int newVal = GL_ZERO;
2607 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2608 case D3DBLEND_ONE : newVal = GL_ONE; break;
2609 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2610 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2611 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2612 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2613 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2614 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2615 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2616 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2617 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2619 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2620 This->srcBlend = newVal;
2621 This->dstBlend = newVal;
2624 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2625 This->srcBlend = newVal;
2626 This->dstBlend = newVal;
2629 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2632 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2633 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2634 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2635 glBlendFunc(This->srcBlend, This->dstBlend);
2637 checkGLcall("glBlendFunc");
2641 case WINED3DRS_ALPHATESTENABLE :
2643 glEnable(GL_ALPHA_TEST);
2644 checkGLcall("glEnable GL_ALPHA_TEST");
2646 glDisable(GL_ALPHA_TEST);
2647 checkGLcall("glDisable GL_ALPHA_TEST");
2651 case WINED3DRS_ALPHAFUNC :
2653 int glParm = GL_LESS;
2654 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2656 switch ((D3DCMPFUNC) Value) {
2657 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2658 case D3DCMP_LESS: glParm = GL_LESS; break;
2659 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2660 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2661 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2662 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2663 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2664 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2666 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2668 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2669 glAlphaFunc(glParm, ref);
2670 This->alphafunc = glParm;
2671 checkGLcall("glAlphaFunc");
2675 case WINED3DRS_ALPHAREF :
2677 int glParm = This->alphafunc;
2680 ref = ((float) Value) / 255.0f;
2681 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2682 glAlphaFunc(glParm, ref);
2683 checkGLcall("glAlphaFunc");
2687 case WINED3DRS_CLIPPLANEENABLE :
2688 case WINED3DRS_CLIPPING :
2690 /* Ensure we only do the changed clip planes */
2691 DWORD enable = 0xFFFFFFFF;
2692 DWORD disable = 0x00000000;
2694 /* If enabling / disabling all */
2695 if (State == WINED3DRS_CLIPPING) {
2697 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2700 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2704 enable = Value & ~OldValue;
2705 disable = ~Value & OldValue;
2708 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2709 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2710 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2711 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2712 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2713 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2715 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2716 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2717 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2718 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2719 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2720 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2722 /** update clipping status */
2724 This->stateBlock->clip_status.ClipUnion = 0;
2725 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2727 This->stateBlock->clip_status.ClipUnion = 0;
2728 This->stateBlock->clip_status.ClipIntersection = 0;
2733 case WINED3DRS_BLENDOP :
2735 int glParm = GL_FUNC_ADD;
2737 switch ((D3DBLENDOP) Value) {
2738 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2739 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2740 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2741 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2742 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2744 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2746 TRACE("glBlendEquation(%x)\n", glParm);
2747 glBlendEquation(glParm);
2748 checkGLcall("glBlendEquation");
2752 case WINED3DRS_TEXTUREFACTOR :
2756 /* Note the texture color applies to all textures whereas
2757 GL_TEXTURE_ENV_COLOR applies to active only */
2759 D3DCOLORTOGLFLOAT4(Value, col);
2760 /* Set the default alpha blend color */
2761 glBlendColor(col[0], col[1], col[2], col[3]);
2762 checkGLcall("glBlendColor");
2764 /* And now the default texture color as well */
2765 for (i = 0; i < GL_LIMITS(textures); i++) {
2767 /* Note the D3DRS value applies to all textures, but GL has one
2768 per texture, so apply it now ready to be used! */
2769 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2772 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2775 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2776 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2781 case WINED3DRS_SPECULARENABLE :
2783 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2784 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2785 specular color. This is wrong:
2786 Separate specular color means the specular colour is maintained separately, whereas
2787 single color means it is merged in. However in both cases they are being used to
2789 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2790 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2794 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2795 checkGLcall("glMaterialfv");
2796 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2797 glEnable(GL_COLOR_SUM_EXT);
2799 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2801 checkGLcall("glEnable(GL_COLOR_SUM)");
2803 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2805 /* for the case of enabled lighting: */
2806 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2807 checkGLcall("glMaterialfv");
2809 /* for the case of disabled lighting: */
2810 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2811 glDisable(GL_COLOR_SUM_EXT);
2813 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2815 checkGLcall("glDisable(GL_COLOR_SUM)");
2820 case WINED3DRS_STENCILENABLE :
2822 glEnable(GL_STENCIL_TEST);
2823 checkGLcall("glEnable GL_STENCIL_TEST");
2825 glDisable(GL_STENCIL_TEST);
2826 checkGLcall("glDisable GL_STENCIL_TEST");
2830 case WINED3DRS_STENCILFUNC :
2832 int glParm = GL_ALWAYS;
2833 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2834 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2836 switch ((D3DCMPFUNC) Value) {
2837 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2838 case D3DCMP_LESS: glParm=GL_LESS; break;
2839 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2840 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2841 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2842 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2843 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2844 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2846 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2848 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2849 This->stencilfunc = glParm;
2850 glStencilFunc(glParm, ref, mask);
2851 checkGLcall("glStencilFunc");
2855 case WINED3DRS_STENCILREF :
2857 int glParm = This->stencilfunc;
2859 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2862 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2863 glStencilFunc(glParm, ref, mask);
2864 checkGLcall("glStencilFunc");
2868 case WINED3DRS_STENCILMASK :
2870 int glParm = This->stencilfunc;
2871 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2872 GLuint mask = Value;
2874 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2875 glStencilFunc(glParm, ref, mask);
2876 checkGLcall("glStencilFunc");
2880 case WINED3DRS_STENCILFAIL :
2886 fail = StencilOp(Value);
2887 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2888 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2889 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2890 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2892 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2893 glStencilOp(fail, zfail, zpass);
2894 checkGLcall("glStencilOp(fail, zfail, zpass);");
2897 case WINED3DRS_STENCILZFAIL :
2903 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2904 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2905 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2906 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2907 zfail = StencilOp(Value);
2909 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2910 glStencilOp(fail, zfail, zpass);
2911 checkGLcall("glStencilOp(fail, zfail, zpass);");
2914 case WINED3DRS_STENCILPASS :
2920 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2921 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2922 zpass = StencilOp(Value);
2923 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2924 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2926 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2927 glStencilOp(fail, zfail, zpass);
2928 checkGLcall("glStencilOp(fail, zfail, zpass);");
2932 case WINED3DRS_STENCILWRITEMASK :
2934 glStencilMask(Value);
2935 TRACE("glStencilMask(%lu)\n", Value);
2936 checkGLcall("glStencilMask");
2940 case WINED3DRS_FOGENABLE :
2942 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2944 checkGLcall("glEnable GL_FOG");
2947 checkGLcall("glDisable GL_FOG");
2952 case WINED3DRS_RANGEFOGENABLE :
2955 TRACE("Enabled RANGEFOG");
2957 TRACE("Disabled RANGEFOG");
2962 case WINED3DRS_FOGCOLOR :
2965 D3DCOLORTOGLFLOAT4(Value, col);
2966 /* Set the default alpha blend color */
2967 glFogfv(GL_FOG_COLOR, &col[0]);
2968 checkGLcall("glFog GL_FOG_COLOR");
2972 case WINED3DRS_FOGTABLEMODE :
2974 glHint(GL_FOG_HINT, GL_NICEST);
2976 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2977 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2978 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2979 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2981 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2983 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2984 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2989 case WINED3DRS_FOGVERTEXMODE :
2991 glHint(GL_FOG_HINT, GL_FASTEST);
2993 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2994 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2995 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2996 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2998 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3000 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3001 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3006 case WINED3DRS_FOGSTART :
3009 glFogfv(GL_FOG_START, &tmpvalue.f);
3010 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3011 TRACE("Fog Start == %f\n", tmpvalue.f);
3015 case WINED3DRS_FOGEND :
3018 glFogfv(GL_FOG_END, &tmpvalue.f);
3019 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3020 TRACE("Fog End == %f\n", tmpvalue.f);
3024 case WINED3DRS_FOGDENSITY :
3027 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3028 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3032 case WINED3DRS_VERTEXBLEND :
3034 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3035 TRACE("Vertex Blending state to %ld\n", Value);
3039 case WINED3DRS_TWEENFACTOR :
3042 This->updateStateBlock->tween_factor = tmpvalue.f;
3043 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3047 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3049 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3053 case WINED3DRS_COLORVERTEX :
3054 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3055 case WINED3DRS_SPECULARMATERIALSOURCE :
3056 case WINED3DRS_AMBIENTMATERIALSOURCE :
3057 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3059 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3061 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3062 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3063 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3064 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3065 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3066 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3068 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3069 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3070 Parm = GL_AMBIENT_AND_DIFFUSE;
3074 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3076 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3078 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3085 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3087 This->tracking_color = NEEDS_TRACKING;
3088 This->tracking_parm = Parm;
3092 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3097 case WINED3DRS_LINEPATTERN :
3103 tmppattern.d = Value;
3105 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3107 if (tmppattern.lp.wRepeatFactor) {
3108 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3109 checkGLcall("glLineStipple(repeat, linepattern)");
3110 glEnable(GL_LINE_STIPPLE);
3111 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3113 glDisable(GL_LINE_STIPPLE);
3114 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3119 case WINED3DRS_ZBIAS :
3123 TRACE("ZBias value %f\n", tmpvalue.f);
3124 glPolygonOffset(0, -tmpvalue.f);
3125 checkGLcall("glPolygonOffset(0, -Value)");
3126 glEnable(GL_POLYGON_OFFSET_FILL);
3127 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3128 glEnable(GL_POLYGON_OFFSET_LINE);
3129 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3130 glEnable(GL_POLYGON_OFFSET_POINT);
3131 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3133 glDisable(GL_POLYGON_OFFSET_FILL);
3134 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3135 glDisable(GL_POLYGON_OFFSET_LINE);
3136 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3137 glDisable(GL_POLYGON_OFFSET_POINT);
3138 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3143 case WINED3DRS_NORMALIZENORMALS :
3145 glEnable(GL_NORMALIZE);
3146 checkGLcall("glEnable(GL_NORMALIZE);");
3148 glDisable(GL_NORMALIZE);
3149 checkGLcall("glDisable(GL_NORMALIZE);");
3153 case WINED3DRS_POINTSIZE :
3155 TRACE("Set point size to %f\n", tmpvalue.f);
3156 glPointSize(tmpvalue.f);
3157 checkGLcall("glPointSize(...);");
3160 case WINED3DRS_POINTSIZE_MIN :
3161 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3163 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3164 checkGLcall("glPointParameterfEXT(...);");
3166 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3170 case WINED3DRS_POINTSIZE_MAX :
3171 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3173 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3174 checkGLcall("glPointParameterfEXT(...);");
3176 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3180 case WINED3DRS_POINTSCALE_A :
3181 case WINED3DRS_POINTSCALE_B :
3182 case WINED3DRS_POINTSCALE_C :
3183 case WINED3DRS_POINTSCALEENABLE :
3185 /* If enabled, supply the parameters, otherwise fall back to defaults */
3186 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3187 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3188 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3189 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3190 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3192 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3193 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3194 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3196 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3199 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3200 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3201 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3202 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3204 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3210 case WINED3DRS_COLORWRITEENABLE :
3212 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3213 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3214 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3215 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3216 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3217 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3218 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3219 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3220 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3221 checkGLcall("glColorMask(...)");
3225 case WINED3DRS_LOCALVIEWER :
3227 GLint state = (Value) ? 1 : 0;
3228 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3229 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3233 case WINED3DRS_LASTPIXEL :
3236 TRACE("Last Pixel Drawing Enabled\n");
3238 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3243 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3246 TRACE("Software Processing Enabled\n");
3248 TRACE("Software Processing Disabled\n");
3253 /** not supported */
3254 case WINED3DRS_ZVISIBLE :
3257 return D3DERR_INVALIDCALL;
3260 /* Unhandled yet...! */
3261 case WINED3DRS_EDGEANTIALIAS :
3262 case WINED3DRS_WRAP0 :
3263 case WINED3DRS_WRAP1 :
3264 case WINED3DRS_WRAP2 :
3265 case WINED3DRS_WRAP3 :
3266 case WINED3DRS_WRAP4 :
3267 case WINED3DRS_WRAP5 :
3268 case WINED3DRS_WRAP6 :
3269 case WINED3DRS_WRAP7 :
3270 case WINED3DRS_POINTSPRITEENABLE :
3271 case WINED3DRS_MULTISAMPLEANTIALIAS :
3272 case WINED3DRS_MULTISAMPLEMASK :
3273 case WINED3DRS_PATCHEDGESTYLE :
3274 case WINED3DRS_PATCHSEGMENTS :
3275 case WINED3DRS_DEBUGMONITORTOKEN :
3276 case WINED3DRS_POSITIONORDER :
3277 case WINED3DRS_NORMALORDER :
3278 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3279 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3282 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3290 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3291 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3292 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3293 *pValue = This->stateBlock->renderState[State];
3297 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3298 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3300 * SetSampler is designed to allow for more than the standard up to 8 textures
3301 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3302 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3304 * http://developer.nvidia.com/object/General_FAQ.html#t6
3306 * There are two new settings for GForce
3308 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3309 * and the texture one:
3310 * GL_MAX_TEXTURE_COORDS_ARB.
3311 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3318 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3320 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3321 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3322 return D3DERR_INVALIDCALL;
3325 This->updateStateBlock->changed.samplerState[Sampler][Type] = TRUE;
3326 This->updateStateBlock->set.samplerState[Sampler][Type] = TRUE;
3327 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3328 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3330 /* Handle recording of state blocks */
3331 if (This->isRecordingState) {
3332 TRACE("Recording... not performing anything\n");
3336 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
3337 clamping, MIPLOD, etc. This will work for up to 16 samplers.
3338 is this just GL_TEXTURE_2D or is it GL_TEXTURE_1D and GL_TEXTURE_3D as well?
3341 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
3342 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3343 GLACTIVETEXTURE(Sampler);
3344 } else if (Sampler > 0) {
3345 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3351 case WINED3DSAMP_ADDRESSU : /* 1 */
3352 case WINED3DSAMP_ADDRESSV : /* 2 */
3353 case WINED3DSAMP_ADDRESSW : /* 3 */
3355 GLint wrapParm = GL_REPEAT;
3357 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3358 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3359 case D3DTADDRESS_BORDER:
3361 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3362 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3364 /* FIXME: Not right, but better */
3365 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3366 wrapParm = GL_REPEAT;
3370 case D3DTADDRESS_MIRROR:
3372 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3373 wrapParm = GL_MIRRORED_REPEAT_ARB;
3375 /* Unsupported in OpenGL pre-1.4 */
3376 TRACE("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3377 wrapParm = GL_REPEAT;
3381 case D3DTADDRESS_MIRRORONCE:
3383 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3384 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3386 TRACE("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3387 wrapParm = GL_REPEAT;
3393 /* This is for the whole context, not just the sampler,
3394 so we should warn if two states are baing set for any given scene */
3396 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3397 wrapParm = GL_REPEAT;
3400 case WINED3DSAMP_ADDRESSU:
3401 TRACE("Setting WRAP_S for %ld to %d \n", Sampler, wrapParm);
3402 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_S, wrapParm);
3403 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3405 case WINED3DSAMP_ADDRESSV:
3406 TRACE("Setting WRAP_T for %ld to %d\n", Sampler, wrapParm);
3407 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_T, wrapParm);
3408 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3411 case WINED3DSAMP_ADDRESSW:
3412 TRACE("Setting WRAP_R for %ld to %d\n", Sampler, wrapParm);
3413 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_R, wrapParm);
3414 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3417 break; /** stupic compilator */
3422 case WINED3DSAMP_BORDERCOLOR : /* 4 */
3425 D3DCOLORTOGLFLOAT4(Value, col);
3426 TRACE("Setting border color for %ld to %lx\n", Sampler, Value);
3427 glTexParameterfv(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_BORDER_COLOR, &col[0]);
3428 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3432 case WINED3DSAMP_MAGFILTER : /* 5 */
3434 DWORD ValueMAG = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAGFILTER];
3435 GLint realVal = GL_NEAREST;
3437 if (ValueMAG == D3DTEXF_POINT) {
3438 realVal = GL_NEAREST;
3439 } else if (ValueMAG == D3DTEXF_LINEAR) {
3440 realVal = GL_LINEAR;
3441 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3442 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3443 realVal = GL_LINEAR;
3445 FIXME("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3446 realVal = GL_NEAREST;
3449 FIXME("Unhandled WINED3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3450 realVal = GL_NEAREST;
3452 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3453 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAG_FILTER, realVal);
3454 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3456 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3458 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3459 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3460 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3461 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3462 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3467 case WINED3DSAMP_MINFILTER: /* 6 */
3468 case WINED3DSAMP_MIPFILTER: /* 7 */
3470 DWORD ValueMIN = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MINFILTER];
3471 DWORD ValueMIP = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPFILTER];
3472 GLint realVal = GL_LINEAR;
3474 if (ValueMIN == D3DTEXF_NONE) {
3475 /* Doesn't really make sense - Windows just seems to disable
3476 mipmapping when this occurs */
3477 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3478 realVal = GL_LINEAR;
3479 } else if (ValueMIN == D3DTEXF_POINT) {
3481 if (ValueMIP == D3DTEXF_NONE) {
3482 realVal = GL_NEAREST;
3483 } else if (ValueMIP == D3DTEXF_POINT) {
3484 realVal = GL_NEAREST_MIPMAP_NEAREST;
3485 } else if (ValueMIP == D3DTEXF_LINEAR) {
3486 realVal = GL_NEAREST_MIPMAP_LINEAR;
3488 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3489 realVal = GL_NEAREST;
3491 } else if (ValueMIN == D3DTEXF_LINEAR) {
3493 if (ValueMIP == D3DTEXF_NONE) {
3494 realVal = GL_LINEAR;
3495 } else if (ValueMIP == D3DTEXF_POINT) {
3496 realVal = GL_LINEAR_MIPMAP_NEAREST;
3497 } else if (ValueMIP == D3DTEXF_LINEAR) {
3498 realVal = GL_LINEAR_MIPMAP_LINEAR;
3500 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3501 realVal = GL_LINEAR;
3503 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3504 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3505 if (ValueMIP == D3DTEXF_NONE) {
3506 realVal = GL_LINEAR_MIPMAP_LINEAR;
3507 } else if (ValueMIP == D3DTEXF_POINT) {
3508 realVal = GL_LINEAR_MIPMAP_NEAREST;
3509 } else if (ValueMIP == D3DTEXF_LINEAR) {
3510 realVal = GL_LINEAR_MIPMAP_LINEAR;
3512 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3513 realVal = GL_LINEAR;
3516 WARN("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3517 realVal = GL_LINEAR;
3520 FIXME("Unhandled WINED3DTSS_MINFILTER value of %ld\n", ValueMIN);
3521 realVal = GL_LINEAR_MIPMAP_LINEAR;
3524 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3525 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MIN_FILTER, realVal);
3526 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3528 * if we just choose to use ANISOTROPIC filtering, refresh openGL state
3530 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3531 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAX_ANISOTROPY_EXT,
3532 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3533 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3538 case WINED3DSAMP_MIPMAPLODBIAS : /* 8 */
3540 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3542 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3543 GL_TEXTURE_LOD_BIAS_EXT,
3545 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3550 case WINED3DSAMP_MAXMIPLEVEL : /* 9 */
3553 * Not really the same, but the more apprioprate than nothing
3555 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3556 GL_TEXTURE_BASE_LEVEL,
3557 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXMIPLEVEL]);
3558 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3562 case WINED3DSAMP_MAXANISOTROPY : /* 10 */
3564 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3565 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3566 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3567 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3568 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3572 case WINED3DSAMP_SRGBTEXTURE : /* 11 */
3573 /* Per texture gamma correction, default 0 */
3574 case WINED3DSAMP_ELEMENTINDEX : /* 12 */
3575 /* When a multi-element textures is used this indicates the element, (what's a multielement texture?) */
3576 case WINED3DSAMP_DMAPOFFSET : /* 13 */
3577 /* Value of a precompiled displacement map used by the tesselator, default 0 */
3578 TRACE("Unsupported sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3582 TRACE("invalid sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3588 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3589 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3590 /** TODO: check that sampler is in range **/
3591 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3592 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3597 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3598 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3601 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3602 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3603 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3608 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3609 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3610 GLint scissorBox[4];
3613 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3614 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3615 pRect->left = scissorBox[1];
3616 pRect->top = scissorBox[2];
3617 pRect->right = scissorBox[1] + scissorBox[3];
3618 pRect->bottom = scissorBox[2] + scissorBox[4];
3619 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3624 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3627 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3629 /* TODO: what about recording stateblocks? */
3630 if (NULL != pDecl) {
3631 IWineD3DVertexDeclaration_AddRef(pDecl);
3633 if (NULL != This->updateStateBlock->vertexDecl) {
3634 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3636 This->updateStateBlock->vertexDecl = pDecl;
3637 This->updateStateBlock->changed.vertexDecl = TRUE;
3638 This->updateStateBlock->set.vertexDecl = TRUE;
3642 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3643 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3645 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3647 *ppDecl = This->updateStateBlock->vertexDecl;
3648 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3652 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3653 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3655 static BOOL showFixmes = TRUE;
3657 This->updateStateBlock->vertexShader = pShader;
3658 This->updateStateBlock->changed.vertexShader = TRUE;
3659 This->updateStateBlock->set.vertexShader = TRUE;
3661 if(pShader == NULL) {
3662 /* clear down the shader */
3663 TRACE("Clear down the shader\n");
3666 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3673 /** FIXME: refernece counting? **/
3674 if (pShader == NULL) { /* only valid with non FVF shaders */
3675 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3676 This->updateStateBlock->vertexShader = NULL;
3678 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3679 This->updateStateBlock->vertexShader = pShader;
3682 This->updateStateBlock->changed.vertexShader = TRUE;
3683 This->updateStateBlock->set.vertexShader = TRUE;
3685 /* Handle recording of state blocks */
3686 if (This->isRecordingState) {
3687 TRACE("Recording... not performing anything\n");
3691 * TODO: merge HAL shaders context switching from prototype
3697 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3698 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3699 *ppShader = This->stateBlock->vertexShader;
3700 if(*ppShader != NULL)
3701 IWineD3DVertexShader_AddRef(*ppShader);
3702 TRACE("(%p) : returning %p\n", This, *ppShader);
3706 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3707 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3709 TRACE("(%p) : stub\n", This);
3713 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3714 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3715 TRACE("(%p) : stub\n", This);
3719 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3720 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3721 TRACE("(%p) : stub\n", This);
3725 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3726 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3727 TRACE("(%p) : stub\n", This);
3731 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3732 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3733 TRACE("(%p) : stub\n", This);
3737 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3739 TRACE("(%p) : stub\n", This);
3743 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3744 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3745 TRACE("(%p) : stub\n", This);
3749 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3750 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3751 TRACE("(%p) : stub\n", This);
3756 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3757 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3758 TRACE("(%p) : stub\n", This);
3762 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3763 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3764 TRACE("(%p) : stub\n", This);
3768 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3769 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3770 TRACE("(%p) : stub\n", This);
3774 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3775 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3776 TRACE("(%p) : stub\n", This);
3780 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3781 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3782 TRACE("(%p) : stub\n", This);
3786 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3787 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3788 TRACE("(%p) : stub\n", This);
3792 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3793 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3794 FIXME("(%p) : stub\n", This);
3799 * Get / Set Texture Stage States
3800 * TODO: Verify against dx9 definitions
3802 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3803 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3805 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3807 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3809 /* Reject invalid texture units */
3810 if (Stage >= GL_LIMITS(textures)) {
3811 TRACE("Attempt to access invalid texture rejected\n");
3812 return D3DERR_INVALIDCALL;
3815 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3816 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3817 This->updateStateBlock->textureState[Stage][Type] = Value;
3819 /* Handle recording of state blocks */
3820 if (This->isRecordingState) {
3821 TRACE("Recording... not performing anything\n");
3827 /* Make appropriate texture active */
3828 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3829 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3830 GLACTIVETEXTURE(Stage);
3831 } else if (Stage > 0) {
3832 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3836 case WINED3DTSS_ALPHAOP :
3837 case WINED3DTSS_COLOROP :
3840 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3841 /* TODO: Disable by making this and all later levels disabled */
3842 glDisable(GL_TEXTURE_1D);
3843 checkGLcall("Disable GL_TEXTURE_1D");
3844 glDisable(GL_TEXTURE_2D);
3845 checkGLcall("Disable GL_TEXTURE_2D");
3846 glDisable(GL_TEXTURE_3D);
3847 checkGLcall("Disable GL_TEXTURE_3D");
3848 break; /* Don't bother setting the texture operations */
3850 /* Enable only the appropriate texture dimension */
3851 if (Type == WINED3DTSS_COLOROP) {
3852 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3853 glEnable(GL_TEXTURE_1D);
3854 checkGLcall("Enable GL_TEXTURE_1D");
3856 glDisable(GL_TEXTURE_1D);
3857 checkGLcall("Disable GL_TEXTURE_1D");
3859 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3860 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3861 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3862 checkGLcall("Enable GL_TEXTURE_2D");
3864 glEnable(GL_TEXTURE_2D);
3865 checkGLcall("Enable GL_TEXTURE_2D");
3868 glDisable(GL_TEXTURE_2D);
3869 checkGLcall("Disable GL_TEXTURE_2D");
3871 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3872 glEnable(GL_TEXTURE_3D);
3873 checkGLcall("Enable GL_TEXTURE_3D");
3875 glDisable(GL_TEXTURE_3D);
3876 checkGLcall("Disable GL_TEXTURE_3D");
3878 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3879 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3880 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3882 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3883 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3887 /* Drop through... (Except disable case) */
3888 case WINED3DTSS_COLORARG0 :
3889 case WINED3DTSS_COLORARG1 :
3890 case WINED3DTSS_COLORARG2 :
3891 case WINED3DTSS_ALPHAARG0 :
3892 case WINED3DTSS_ALPHAARG1 :
3893 case WINED3DTSS_ALPHAARG2 :
3895 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3896 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3898 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3899 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3900 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3901 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3903 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3904 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3905 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3906 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3912 case WINED3DTSS_ADDRESSW :
3914 GLint wrapParm = GL_REPEAT;
3917 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3918 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3919 case D3DTADDRESS_BORDER:
3921 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3922 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3924 /* FIXME: Not right, but better */
3925 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3926 wrapParm = GL_REPEAT;
3930 case D3DTADDRESS_MIRROR:
3932 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3933 wrapParm = GL_MIRRORED_REPEAT_ARB;
3935 /* Unsupported in OpenGL pre-1.4 */
3936 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3937 wrapParm = GL_REPEAT;
3941 case D3DTADDRESS_MIRRORONCE:
3943 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3944 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3946 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3947 wrapParm = GL_REPEAT;
3953 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3954 wrapParm = GL_REPEAT;
3957 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3958 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3959 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3963 case WINED3DTSS_TEXCOORDINDEX :
3965 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3967 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3968 one flag, you can still specify an index value, which the system uses to
3969 determine the texture wrapping mode.
3970 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3971 means use the vertex position (camera-space) as the input texture coordinates
3972 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3973 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3974 to the TEXCOORDINDEX value */
3977 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3979 switch (Value & 0xFFFF0000) {
3980 case D3DTSS_TCI_PASSTHRU:
3981 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3982 glDisable(GL_TEXTURE_GEN_S);
3983 glDisable(GL_TEXTURE_GEN_T);
3984 glDisable(GL_TEXTURE_GEN_R);
3985 glDisable(GL_TEXTURE_GEN_Q);
3986 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3989 case D3DTSS_TCI_CAMERASPACEPOSITION:
3990 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3991 as the input texture coordinates for this stage's texture transformation. This
3992 equates roughly to EYE_LINEAR */
3994 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3995 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3996 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3997 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3998 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4000 glMatrixMode(GL_MODELVIEW);
4003 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4004 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4005 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4006 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4009 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4010 glEnable(GL_TEXTURE_GEN_S);
4011 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4012 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4013 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4014 glEnable(GL_TEXTURE_GEN_T);
4015 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4016 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4017 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4018 glEnable(GL_TEXTURE_GEN_R);
4019 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4020 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4021 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4025 case D3DTSS_TCI_CAMERASPACENORMAL:
4027 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4028 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4029 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4030 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4031 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4032 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4034 glMatrixMode(GL_MODELVIEW);
4037 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4038 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4039 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4040 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4043 glEnable(GL_TEXTURE_GEN_S);
4044 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4045 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4046 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4047 glEnable(GL_TEXTURE_GEN_T);
4048 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4049 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4050 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4051 glEnable(GL_TEXTURE_GEN_R);
4052 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4053 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4054 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4059 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4061 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4062 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4063 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4064 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4065 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4066 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4068 glMatrixMode(GL_MODELVIEW);
4071 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4072 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4073 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4074 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4077 glEnable(GL_TEXTURE_GEN_S);
4078 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4079 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4080 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4081 glEnable(GL_TEXTURE_GEN_T);
4082 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4083 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4084 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4085 glEnable(GL_TEXTURE_GEN_R);
4086 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4087 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4088 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4093 /* Unhandled types: */
4096 /* ? disable GL_TEXTURE_GEN_n ? */
4097 glDisable(GL_TEXTURE_GEN_S);
4098 glDisable(GL_TEXTURE_GEN_T);
4099 glDisable(GL_TEXTURE_GEN_R);
4100 glDisable(GL_TEXTURE_GEN_Q);
4101 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4108 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4109 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value, (This->stateBlock->textureState[Stage][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
4112 case WINED3DTSS_BUMPENVMAT00 :
4113 case WINED3DTSS_BUMPENVMAT01 :
4114 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4116 case WINED3DTSS_BUMPENVMAT10 :
4117 case WINED3DTSS_BUMPENVMAT11 :
4118 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4121 case WINED3DTSS_BUMPENVLSCALE :
4122 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4125 case WINED3DTSS_BUMPENVLOFFSET :
4126 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4129 case WINED3DTSS_RESULTARG :
4130 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4134 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4135 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4143 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4144 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4145 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4146 *pValue = This->updateStateBlock->textureState[Stage][Type];
4153 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4155 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4156 IWineD3DBaseTexture *oldTexture;
4157 BOOL reapplyStates = TRUE;
4158 DWORD reapplyFlags = 0;
4159 INT oldTextureDimensions = -1;
4160 D3DRESOURCETYPE textureType;
4162 oldTexture = This->updateStateBlock->textures[Stage];
4163 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4165 /* Reject invalid texture units */
4166 if (Stage >= GL_LIMITS(textures)) {
4167 TRACE("Attempt to access invalid texture rejected\n");
4168 return D3DERR_INVALIDCALL;
4171 This->updateStateBlock->set.textures[Stage] = TRUE;
4172 This->updateStateBlock->changed.textures[Stage] = TRUE;
4173 This->updateStateBlock->textures[Stage] = pTexture;
4175 /* Handle recording of state blocks */
4176 if (This->isRecordingState) {
4177 TRACE("Recording... not performing anything\n");
4181 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
4185 /* Make appropriate texture active */
4186 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4187 GLACTIVETEXTURE(Stage);
4189 } else if (Stage>0) {
4190 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
4193 /** NOTE: MSDN says that setTexture increases the reference count,
4194 * and the the application nust set the texture back to null (or have a leaky application),
4195 * This means we should pass the refcount upto the parent
4196 *******************************/
4197 if (NULL != This->updateStateBlock->textures[Stage]) {
4198 IUnknown *textureParent;
4199 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4200 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
4203 if (NULL != oldTexture) {
4204 IUnknown *textureParent;
4205 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4206 IUnknown_Release(textureParent);
4207 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4212 if (NULL != pTexture) {
4213 /* Now setup the texture appropraitly */
4214 textureType = IWineD3DBaseTexture_GetType(pTexture);
4216 if (textureType == D3DRTYPE_TEXTURE) {
4218 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4219 TRACE("Skipping setting texture as old == new\n");
4220 reapplyStates = FALSE;
4224 /* Standard 2D texture */
4225 TRACE("Standard 2d texture\n");
4226 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
4228 /* Load up the texture now */
4229 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
4232 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
4234 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4235 TRACE("Skipping setting texture as old == new\n");
4236 reapplyStates = FALSE;
4240 /* Standard 3D (volume) texture */
4241 TRACE("Standard 3d texture\n");
4242 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
4244 /* Load up the texture now */
4245 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
4248 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
4250 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4251 TRACE("Skipping setting texture as old == new\n");
4252 reapplyStates = FALSE;
4256 /* Standard Cube texture */
4257 TRACE("Standard Cube texture\n");
4258 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
4260 /* Load up the texture now */
4261 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
4265 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
4270 TRACE("Setting to no texture (ie default texture)\n");
4271 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
4272 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
4273 checkGLcall("glBindTexture");
4274 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
4277 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
4278 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4280 glDisable(oldTextureDimensions);
4281 checkGLcall("Disable oldTextureDimensions");
4283 if (This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
4284 glEnable(This->updateStateBlock->textureDimensions[Stage]);
4285 checkGLcall("glEnable new texture dimensions");
4288 /* If Alpha arg1 is texture then handle the special case when there changes between a
4289 texture and no texture - See comments in set_tex_op */
4290 if ((This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4291 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4293 reapplyFlags |= REAPPLY_ALPHAOP;
4298 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4299 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4300 if (reapplyStates) {
4301 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4305 TRACE("Texture now fully setup\n");
4310 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4311 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4312 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4313 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4315 IWineD3DBaseTexture_AddRef(*ppTexture);
4322 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4323 IWineD3DSurface** ppBackBuffer) {
4324 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4325 IWineD3DSwapChain *swapChain;
4328 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4330 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4332 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4333 IWineD3DSwapChain_Release(swapChain);
4335 *ppBackBuffer = NULL;
4340 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4341 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4342 WARN("(%p) : stub, calling idirect3d for now\n", This);
4343 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4346 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4347 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4348 IWineD3DSwapChain *swapChain;
4351 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4353 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4354 IWineD3DSwapChain_Release(swapChain);
4356 FIXME("(%p) Error getting display mode\n", This);
4361 * Stateblock related functions
4364 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4365 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4366 IWineD3DStateBlockImpl *object;
4367 TRACE("(%p)", This);
4368 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4369 if(NULL == object ) {
4370 FIXME("(%p)Error allocating memory for stateblock\n", This);
4371 return E_OUTOFMEMORY;
4373 TRACE("(%p) creted object %p\n", This, object);
4374 object->wineD3DDevice= This;
4375 /** FIXME: object->parent = parent; **/
4376 object->parent = NULL;
4377 object->blockType = WINED3DSBT_ALL;
4379 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4381 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4382 This->updateStateBlock = object;
4383 This->isRecordingState = TRUE;
4385 TRACE("(%p) recording stateblock %p\n",This , object);
4389 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4390 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4392 if (!This->isRecordingState) {
4393 FIXME("(%p) not recording! returning error\n", This);
4394 *ppStateBlock = NULL;
4395 return D3DERR_INVALIDCALL;
4398 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4399 This->isRecordingState = FALSE;
4400 This->updateStateBlock = This->stateBlock;
4401 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4402 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4403 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4408 * Scene related functions
4410 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4411 /* At the moment we have no need for any functionality at the beginning
4413 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4414 TRACE("(%p) : stub\n", This);
4418 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4420 TRACE("(%p)\n", This);
4422 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4424 checkGLcall("glFlush");
4426 TRACE("End Scene\n");
4427 if(This->renderTarget != NULL) {
4429 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4430 IUnknown *targetContainer = NULL;
4431 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4432 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4433 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4434 /** always dirtify for now. we must find a better way to see that surface have been modified
4435 (Modifications should will only occur via draw-primitive, but we do need better locking
4436 switching to render-to-texture should remove the overhead though.
4438 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4439 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4440 IWineD3DSurface_PreLoad(This->renderTarget);
4441 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4442 IUnknown_Release(targetContainer);
4445 This->sceneEnded = TRUE;
4450 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4451 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4452 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4453 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4454 IWineD3DSwapChain *swapChain = NULL;
4456 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4458 TRACE("(%p) Presenting the frame\n", This);
4460 for(i = 0 ; i < swapchains ; i ++) {
4462 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4463 TRACE("presentinng chain %d, %p\n", i, swapChain);
4464 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4465 IWineD3DSwapChain_Release(swapChain);
4471 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4472 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4473 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4475 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4476 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4477 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4478 GLbitfield glMask = 0;
4479 GLboolean old_ztest;
4480 GLfloat old_z_clear_value;
4481 GLint old_stencil_clear_value;
4482 GLfloat old_color_clear_value[4];
4484 CONST D3DRECT* curRect;
4486 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4487 Count, pRects, Flags, Z, Stencil);
4491 glEnable(GL_SCISSOR_TEST);
4492 checkGLcall("glEnable GL_SCISSOR_TEST");
4494 if (Count > 0 && pRects) {
4500 /* Only set the values up once, as they are not changing */
4501 if (Flags & D3DCLEAR_STENCIL) {
4502 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4503 glClearStencil(Stencil);
4504 checkGLcall("glClearStencil");
4505 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4506 glStencilMask(0xFFFFFFFF);
4509 if (Flags & D3DCLEAR_ZBUFFER) {
4510 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4511 glDepthMask(GL_TRUE);
4512 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4514 checkGLcall("glClearDepth");
4515 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4518 if (Flags & D3DCLEAR_TARGET) {
4519 TRACE("Clearing screen with glClear to color %lx\n", Color);
4520 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4521 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4522 ((Color >> 8) & 0xFF) / 255.0f,
4523 ((Color >> 0) & 0xFF) / 255.0f,
4524 ((Color >> 24) & 0xFF) / 255.0f);
4525 checkGLcall("glClearColor");
4527 /* Clear ALL colors! */
4528 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4529 glMask = glMask | GL_COLOR_BUFFER_BIT;
4532 /* Now process each rect in turn */
4533 for (i = 0; i < Count || i == 0; i++) {
4536 /* Note gl uses lower left, width/height */
4537 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4538 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4539 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4540 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4541 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4542 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4543 checkGLcall("glScissor");
4545 glScissor(This->stateBlock->viewport.X,
4546 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4547 This->stateBlock->viewport.Width,
4548 This->stateBlock->viewport.Height);
4549 checkGLcall("glScissor");
4552 /* Clear the selected rectangle (or full screen) */
4554 checkGLcall("glClear");
4556 /* Step to the next rectangle */
4557 if (curRect) curRect = curRect + sizeof(D3DRECT);
4560 /* Restore the old values (why..?) */
4561 if (Flags & D3DCLEAR_STENCIL) {
4562 glClearStencil(old_stencil_clear_value);
4563 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4565 if (Flags & D3DCLEAR_ZBUFFER) {
4566 glDepthMask(old_ztest);
4567 glClearDepth(old_z_clear_value);
4569 if (Flags & D3DCLEAR_TARGET) {
4570 glClearColor(old_color_clear_value[0],
4571 old_color_clear_value[1],
4572 old_color_clear_value[2],
4573 old_color_clear_value[3]);
4574 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4575 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4576 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4577 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4580 glDisable(GL_SCISSOR_TEST);
4581 checkGLcall("glDisable");
4590 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4591 UINT PrimitiveCount) {
4593 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4594 This->stateBlock->streamIsUP = FALSE;
4596 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4597 debug_d3dprimitivetype(PrimitiveType),
4598 StartVertex, PrimitiveCount);
4599 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4604 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4605 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4606 D3DPRIMITIVETYPE PrimitiveType,
4607 INT baseVIndex, UINT minIndex,
4608 UINT NumVertices,UINT startIndex,UINT primCount) {
4610 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4612 IWineD3DIndexBuffer *pIB;
4613 D3DINDEXBUFFER_DESC IdxBufDsc;
4615 pIB = This->stateBlock->pIndexData;
4616 This->stateBlock->streamIsUP = FALSE;
4618 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4619 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4620 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4622 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4623 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4629 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4630 startIndex, idxStride,
4631 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4637 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4638 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4639 UINT VertexStreamZeroStride) {
4640 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4642 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4643 debug_d3dprimitivetype(PrimitiveType),
4644 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4646 if (This->stateBlock->streamSource[0] != NULL) {
4647 IUnknown *vertexBufferParent;
4648 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4649 IUnknown_Release(vertexBufferParent);
4650 IUnknown_Release(vertexBufferParent);
4653 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4654 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4655 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4656 This->stateBlock->streamIsUP = TRUE;
4657 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4658 This->stateBlock->streamStride[0] = 0;
4659 This->stateBlock->streamSource[0] = NULL;
4661 /*stream zero settings set to null at end, as per the msdn */
4665 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4666 UINT MinVertexIndex,
4667 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4668 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4669 UINT VertexStreamZeroStride) {
4671 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4673 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4674 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4675 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4676 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4678 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4684 if (This->stateBlock->streamSource[0] != NULL) {
4685 IUnknown *vertexBufferParent;
4686 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4687 This->stateBlock->streamSource[0] = NULL;
4688 IUnknown_Release(vertexBufferParent);
4689 IUnknown_Release(vertexBufferParent);
4692 if (This->stateBlock->pIndexData) {
4693 IUnknown *indexBufferParent;
4694 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4695 This->stateBlock->pIndexData = NULL;
4696 IUnknown_Release(indexBufferParent);
4697 IUnknown_Release(indexBufferParent);
4700 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4701 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4702 This->stateBlock->streamIsUP = TRUE;
4703 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4705 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4707 /* stream zero settings set to null at end as per the msdn */
4708 This->stateBlock->streamSource[0] = NULL;
4709 This->stateBlock->streamStride[0] = 0;
4714 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4715 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4716 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4717 D3DRESOURCETYPE sourceType;
4718 D3DRESOURCETYPE destinationType;
4719 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4720 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4723 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4724 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4725 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4726 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4727 return D3DERR_INVALIDCALL;
4729 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4731 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4732 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4733 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4735 /* Make sure that the destination texture is loaded */
4736 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4737 TRACE("Loading source texture\n");
4739 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4740 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4741 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4744 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4745 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4747 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4748 return D3DERR_INVALIDCALL;
4750 /** TODO: check that both textures have the same number of levels **/
4752 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4753 return D3DERR_INVALIDCALL;
4755 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4756 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4757 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4763 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4764 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4765 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4766 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4768 TRACE("(%p) : stub\n", This);
4771 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4772 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4774 TRACE("(%p) : stub\n", This);
4778 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4779 IWineD3DSwapChain *swapChain;
4781 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4783 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4784 IWineD3DSwapChain_Release(swapChain);
4789 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4790 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4791 /* return a sensible default */
4793 FIXME("(%p) : stub\n", This);
4797 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4798 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4799 FIXME("(%p) : stub\n", This);
4803 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4804 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4805 FIXME("(%p) : stub\n", This);
4809 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4810 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4811 FIXME("(%p) : stub\n", This);
4815 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4816 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4817 FIXME("(%p) : stub\n", This);
4821 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4822 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4823 FIXME("(%p) : stub\n", This);
4828 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4829 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4830 FIXME("(%p) : stub\n", This);
4835 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4836 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4838 pRasterStatus->InVBlank = TRUE;
4839 pRasterStatus->ScanLine = 0;
4840 FIXME("(%p) : stub\n", This);
4845 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4846 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4847 static BOOL showfixmes = TRUE;
4848 if(nSegments != 0.0f) {
4850 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4857 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4858 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4859 static BOOL showfixmes = TRUE;
4861 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4868 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4869 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4870 /** TODO: remove casts to IWineD3DSurfaceImpl
4871 * NOTE: move code to surface to accomplish this
4872 ****************************************/
4873 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4874 int srcWidth, srcHeight, srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4875 WINED3DFORMAT destFormat, srcFormat;
4877 int destLeft, destTop;
4878 D3DPOOL srcPool, destPool;
4880 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4881 glDescriptor *glDescription = NULL;
4882 GLenum textureDimensions = GL_TEXTURE_2D;
4883 IWineD3DBaseTexture *baseTexture;
4885 WINED3DSURFACE_DESC winedesc;
4887 memset(&winedesc, 0, sizeof(winedesc));
4888 winedesc.Width = &srcSurfaceWidth;
4889 winedesc.Height = &srcSurfaceHeight;
4890 winedesc.Pool = &srcPool;
4891 winedesc.Format = &srcFormat;
4893 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4895 winedesc.Width = &destSurfaceWidth;
4896 winedesc.Height = &destSurfaceHeight;
4897 winedesc.Pool = &destPool;
4898 winedesc.Format = &destFormat;
4899 winedesc.Size = &destSize;
4901 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4903 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
4904 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4905 return D3DERR_INVALIDCALL;
4907 /* TODO: change this to use bindTexture */
4908 /* Make sure the surface is loaded and upto date */
4909 IWineD3DSurface_PreLoad(pDestinationSurface);
4911 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4915 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4916 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4917 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4918 destLeft = pDestPoint ? pDestPoint->x : 0;
4919 destTop = pDestPoint ? pDestPoint->y : 0;
4922 /* This function doesn't support compressed textures
4923 the pitch is just bytesPerPixel * width */
4925 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
4926 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4927 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
4928 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4930 /* TODO DXT formats */
4932 if(pSourceRect != NULL && pSourceRect->top != 0){
4933 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4935 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4937 ,glDescription->level
4942 ,glDescription->glFormat
4943 ,glDescription->glType
4944 ,IWineD3DSurface_GetData(pSourceSurface)
4948 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4949 /* need to lock the surface to get the data */
4950 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4952 /* TODO: Cube and volume support */
4954 /* not a whole row so we have to do it a line at a time */
4956 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4957 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4959 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4961 glTexSubImage2D(glDescription->target
4962 ,glDescription->level
4967 ,glDescription->glFormat
4968 ,glDescription->glType
4969 ,data/* could be quicker using */
4974 } else { /* Full width, so just write out the whole texture */
4976 if (WINED3DFMT_DXT1 == destFormat ||
4977 WINED3DFMT_DXT3 == destFormat ||
4978 WINED3DFMT_DXT5 == destFormat) {
4979 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4980 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4981 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4982 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4983 } if (destFormat != srcFormat) {
4984 FIXME("Updating mixed format compressed texture is not curretly support\n");
4986 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
4987 glDescription->level,
4988 glDescription->glFormatInternal,
4993 IWineD3DSurface_GetData(pSourceSurface));
4996 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5001 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5002 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5003 data returned by GetData non-power2 width/height with hardware non-power2
5004 pow2Width/height are set to surface width height, repacking isn't needed so it
5005 doesn't matter which function gets called. */
5006 glTexSubImage2D(glDescription->target
5007 ,glDescription->level
5012 ,glDescription->glFormat
5013 ,glDescription->glType
5014 ,IWineD3DSurface_GetData(pSourceSurface)
5019 checkGLcall("glTexSubImage2D");
5020 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5021 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5022 * surface bigger than it needs to be hmm.. */
5023 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5024 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5025 IWineD3DBaseTexture_Release(baseTexture);
5028 glDisable(textureDimensions); /* This needs to be managed better.... */
5034 /* Implementation details at http://developer.nvidia.com/attach/6494
5036 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5037 hmm.. no longer supported use
5038 OpenGL evaluators or tessellate surfaces within your application.
5041 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5042 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5043 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5044 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
5045 FIXME("(%p) : Stub\n", This);
5050 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5051 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5052 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5053 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
5054 FIXME("(%p) : Stub\n", This);
5058 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5059 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5060 TRACE("(%p) Handle(%d)\n", This, Handle);
5061 FIXME("(%p) : Stub\n", This);
5065 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5066 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5067 fill a surface with a block of color! */
5068 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5069 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5070 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5071 IWineD3DSwapChainImpl *container = NULL;
5072 BOOL isRenderTarget = FALSE;
5073 unsigned int width, height;
5074 unsigned int top, left;
5077 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5078 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5079 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5080 return D3DERR_INVALIDCALL;
5083 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5084 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5085 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5086 /* TODO: make sure we set everything back to the way it was, and context management!
5087 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5088 vcheckGLcall("glIntegerv");
5089 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5090 vcheckGLcall("glIntegerv");
5092 TRACE("Color fill to render targets may cause some graphics issues\n");
5093 if (pSurface == container->frontBuffer) {
5094 glDrawBuffer(GL_FRONT);
5096 glDrawBuffer(GL_BACK);
5099 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5100 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
5102 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5104 if (container != NULL) {
5105 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5107 /* we can use GL_STENCIL_INDEX etc...*/
5110 if (container != NULL) {
5111 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5113 isRenderTarget = TRUE;
5115 /* TODO: drawing to GL_FRONT and GL_BACK */
5116 /* TODO: see if things can be speeded up by using the correct
5117 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5118 if (pRect == NULL) {
5121 width = surface->currentDesc.Width;
5122 height = surface->currentDesc.Height;
5126 width = pRect->x2 - left;
5127 height = pRect->y2 - top;
5130 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5131 /* Create a 'line' of color color, in the correct format for the surface */
5132 for (u = 0 ; u < width ; u ++) {
5137 if (isRenderTarget == FALSE) {
5138 glDescriptor *glDesc;
5139 IWineD3DSurface_PreLoad(pSurface);
5141 /* draw a block of the coloured line on the sufrace */
5142 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5143 for (v = 0 ; v< height;v++) {
5144 glTexSubImage2D(glDesc->target
5145 ,glDesc->level /* level */
5155 checkGLcall("glTexSubImage2D");
5157 glDisable(glDesc->target);
5159 /** FIXME: Using GLClear may be faster **/
5160 glRasterPos2i(left, top);
5161 glPixelZoom((float)width ,(float)height);
5162 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5163 checkGLcall("glDrawPixels");
5165 HeapFree(GetProcessHeap(), 0, data);
5171 /* rendertarget and deptth stencil functions */
5172 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5173 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5175 /* FIXME: Implelent RenderTargetIndex >0 */
5176 if(RenderTargetIndex > 0)
5177 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5179 *ppRenderTarget = This->renderTarget;
5180 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5181 /* Note inc ref on returned surface */
5182 if(*ppRenderTarget != NULL)
5183 IWineD3DSurface_AddRef(*ppRenderTarget);
5187 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5188 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5189 *ppZStencilSurface = This->depthStencilBuffer;
5190 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5192 if(*ppZStencilSurface != NULL) {
5193 /* Note inc ref on returned surface */
5194 IWineD3DSurface_AddRef(*ppZStencilSurface);
5199 /* internal static helper functions */
5200 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5201 IWineD3DSurface *RenderSurface);
5203 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
5205 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
5207 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5208 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5209 HRESULT hr = D3D_OK;
5210 WINED3DVIEWPORT viewport;
5212 TRACE("(%p) Swapping rendertarget\n",This);
5213 if (RenderTargetIndex > 0) {
5214 FIXME("(%p) Render targets other than the first are not supported\n",This);
5215 RenderTargetIndex = 0;
5218 /* MSDN says that null disables the render target
5219 but a device must always be associated with a render target
5220 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5222 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5225 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5226 FIXME("Trying to set render target 0 to NULL\n");
5227 return D3DERR_INVALIDCALL;
5229 /* TODO: replace Impl* usage with interface usage */
5230 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5231 FIXME("(%p)Trying to set the render target to a surface(%p) that wasn't created with a usage of D3DUSAGE_RENDERTARGET\n",This ,pRenderTarget);
5232 return D3DERR_INVALIDCALL;
5234 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5235 * builds, but I think wine counts as a 'debug' build for now.
5236 ******************************/
5237 /* If we are trying to set what we already have, don't bother */
5238 if (pRenderTarget == This->renderTarget) {
5239 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5241 /* Otherwise, set the render target up */
5243 if (FALSE == This->sceneEnded) {
5244 IWineD3DDevice_EndScene(iface);
5246 TRACE("clearing renderer\n");
5247 /* IWineD3DDeviceImpl_CleanRender(iface); */
5248 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5249 depending on the renter target implementation being used.
5250 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5251 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5252 stencil buffer and incure an extra memory overhead */
5253 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5256 if (SUCCEEDED(hr)) {
5257 /* Finally, reset the viewport as the MSDN states. */
5258 /* TODO: Replace impl usage */
5259 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5260 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5263 viewport.MaxZ = 1.0f;
5264 viewport.MinZ = 0.0f;
5265 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5267 FIXME("Unknown error setting the render target\n");
5269 This->sceneEnded = FALSE;
5273 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5274 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5275 HRESULT hr = D3D_OK;
5276 IWineD3DSurface *tmp;
5278 TRACE("(%p) Swapping z-buffer\n",This);
5280 if (pNewZStencil == This->stencilBufferTarget) {
5281 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5283 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5284 * depending on the renter target implementation being used.
5285 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5286 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5287 * stencil buffer and incure an extra memory overhead
5288 ******************************************************/
5291 tmp = This->stencilBufferTarget;
5292 This->stencilBufferTarget = pNewZStencil;
5293 /* should we be calling the parent or the wined3d surface? */
5294 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5295 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5297 /** TODO: glEnable/glDisable on depth/stencil depending on
5298 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5299 **********************************************************/
5306 /* Internal functions not in DirectX */
5307 /** TODO: move this off to the opengl context manager
5308 *(the swapchain doesn't need to know anything about offscreen rendering!)
5309 ****************************************************/
5311 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5313 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5315 TRACE("(%p), %p\n", This, swapchain);
5317 if (swapchain->win != swapchain->drawable) {
5318 /* Set everything back the way it ws */
5319 swapchain->render_ctx = swapchain->glCtx;
5320 swapchain->drawable = swapchain->win;
5324 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5325 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5326 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5330 WINED3DFORMAT format;
5331 WINED3DSURFACE_DESC surfaceDesc;
5332 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5333 surfaceDesc.Width = &width;
5334 surfaceDesc.Height = &height;
5335 surfaceDesc.Format = &format;
5336 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5338 /* I need a get width/height function (and should do something with the format) */
5339 for (i = 0; i < CONTEXT_CACHE; ++i) {
5340 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5341 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5342 the pSurface can be set to 0 allowing it to be reused from cache **/
5343 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5344 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5345 *context = &This->contextCache[i];
5348 if (This->contextCache[i].Width == 0) {
5349 This->contextCache[i].pSurface = pSurface;
5350 This->contextCache[i].Width = width;
5351 This->contextCache[i].Height = height;
5352 *context = &This->contextCache[i];
5356 if (i == CONTEXT_CACHE) {
5357 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5358 glContext *dropContext = 0;
5359 for (i = 0; i < CONTEXT_CACHE; i++) {
5360 if (This->contextCache[i].usedcount < minUsage) {
5361 dropContext = &This->contextCache[i];
5362 minUsage = This->contextCache[i].usedcount;
5365 /* clean up the context (this doesn't work for ATI at the moment */
5367 glXDestroyContext(swapchain->display, dropContext->context);
5368 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5371 dropContext->Width = 0;
5372 dropContext->pSurface = pSurface;
5373 *context = dropContext;
5375 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5376 for (i = 0; i < CONTEXT_CACHE; i++) {
5377 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5381 if (*context != NULL)
5384 return E_OUTOFMEMORY;
5387 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5388 * the functionality needs splitting up so that we don't do more than we should do.
5389 * this only seems to impact performance a little.
5390 ******************************/
5391 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5392 IWineD3DSurface *RenderSurface) {
5393 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5395 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5396 HRESULT ret = D3DERR_INVALIDCALL;
5397 IWineD3DSurface *tmp;
5399 * Currently only active for GLX >= 1.3
5400 * for others versions we'll have to use GLXPixmaps
5402 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5403 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5404 * so only check OpenGL version
5405 * ..........................
5406 * I don't believe that it is a problem with NVidia headers,
5407 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5408 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5410 * Your application will report GLX version 1.2 on glXQueryVersion.
5411 * However, it is safe to call the GLX 1.3 functions as described below.
5413 #if defined(GL_VERSION_1_3)
5415 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5416 GLXFBConfig* cfgs = NULL;
5420 IWineD3DSwapChain *currentSwapchain;
5421 IWineD3DSwapChainImpl *swapchain;
5422 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5423 * but switch them off if the StencilSurface is set to NULL
5424 ** *********************************************************/
5425 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5426 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5429 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5430 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5433 #define PUSH1(att) attribs[nAttribs++] = (att);
5434 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5436 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5438 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5439 IWineD3DSwapChainImpl *impSwapChain;
5440 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5441 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5442 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5447 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5448 PUSH2(GLX_X_RENDERABLE, TRUE);
5449 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5450 TRACE("calling makeglcfg\n");
5451 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5454 TRACE("calling chooseFGConfig\n");
5455 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5458 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5459 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5460 why we failed and only show this message once! */
5461 MESSAGE("Failed to find exact match, finding alternative but you may suffer performance issues, try changing xfree's depth to match the requested depth\n"); /**/
5463 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5464 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5465 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5466 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5467 TRACE("calling makeglcfg\n");
5468 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5470 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5477 for (i = 0; i < nCfgs; ++i) {
5478 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5479 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5480 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5483 if (NULL != This->renderTarget) {
5485 vcheckGLcall("glFlush");
5486 /** This is only useful if the old render target was a swapchain,
5487 * we need to supercede this with a function that displays
5488 * the current buffer on the screen. This is easy to do in glx1.3 but
5489 * we need to do copy-write pixels in glx 1.2.
5490 ************************************************/
5491 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5493 printf("Hit Enter to get next frame ...\n");
5499 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5500 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5501 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5505 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5506 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5507 **********************************************************************/
5508 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5509 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5510 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5511 TRACE("making swapchain active\n");
5512 if (RenderSurface != This->renderTarget) {
5513 if (RenderSurface == swapchain->backBuffer) {
5515 /* This could be flagged so that some operations work directly with the front buffer */
5516 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5518 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5520 TRACE("Error in setting current context: context %p drawable %ld !\n",
5521 impSwapChain->glCtx, impSwapChain->win);
5524 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5526 checkGLcall("glXMakeContextCurrent");
5528 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5530 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5532 /** ********************************************************************
5533 * This is a quickly hacked out implementation of offscreen textures.
5534 * It will work in most cases but there may be problems if the client
5535 * modifies the texture directly, or expects the contents of the rendertarget
5538 * There are some real speed vs compatibility issues here:
5539 * we should really use a new context for every texture, but that eats ram.
5540 * we should also be restoring the texture to the pbuffer but that eats CPU
5541 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5542 * but if this means reusing the display backbuffer then we need to make sure that
5543 * states are correctly preserved.
5544 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5545 * and gain a good performance increase at the cost of compatibility.
5546 * I would suggest that, when this is the case, a user configurable flag be made
5547 * available, allowing the user to choose the best emmulated experience for them.
5548 *********************************************************************/
5550 XVisualInfo *visinfo;
5551 glContext *newContext;
5553 /* Here were using a shared context model */
5554 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5555 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5558 /* If the context doesn't exist then create a new one */
5559 /* TODO: This should really be part of findGlContext */
5560 if (NULL == newContext->context) {
5562 TRACE("making new buffer\n");
5564 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5565 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5568 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5570 /** ****************************************
5571 *GLX1.3 isn't supported by XFree 'yet' untill that point ATI emulates pBuffers
5573 * In future releases, we may provide the calls glXCreateNewContext,
5574 * glXQueryDrawable and glXMakeContextCurrent.
5575 * so until then we have to use glXGetVisualFromFBConfig &co..
5576 ********************************************/
5579 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5581 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5583 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5587 if (NULL == newContext || NULL == newContext->context) {
5588 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5590 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5591 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5592 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5595 /* Clean up the old context */
5596 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5597 /* Set the current context of the swapchain to the new context */
5598 impSwapChain->drawable = newContext->drawable;
5599 impSwapChain->render_ctx = newContext->context;
5603 #if 0 /* Apply the stateblock to the new context
5604 FIXME: This is a bit of a hack, each context should know it's own state,
5605 the directX current directX state should then be applied to the context */
5608 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5609 oldUpdateStateBlock = This->updateStateBlock;
5610 oldRecording= This->isRecordingState;
5611 This->isRecordingState = FALSE;
5612 This->updateStateBlock = This->stateBlock;
5613 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5615 This->isRecordingState = oldRecording;
5616 This->updateStateBlock = oldUpdateStateBlock;
5620 /* clean up the current rendertargets swapchain (if it belonged to one) */
5621 if (currentSwapchain != NULL) {
5622 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5625 /* Were done with the opengl context management, setup the rendertargets */
5627 tmp = This->renderTarget;
5628 This->renderTarget = RenderSurface;
5629 IWineD3DSurface_AddRef(This->renderTarget);
5630 IWineD3DSurface_Release(tmp);
5636 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5637 /* Check that the container is not a swapchain member */
5639 IWineD3DSwapChain *tmpSwapChain;
5640 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5641 This->renderUpsideDown = TRUE;
5643 This->renderUpsideDown = FALSE;
5644 IWineD3DSwapChain_Release(tmpSwapChain);
5646 /* Force updating the cull mode */
5647 TRACE("setting render state\n");
5648 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5649 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5651 /* Force updating projection matrix */
5652 This->last_was_rhw = FALSE;
5653 This->proj_valid = FALSE;
5661 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5662 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5667 if ( NULL != impSwapChain) {
5668 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5676 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5677 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5678 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5679 /* TODO: the use of Impl is deprecated. */
5680 /* some basic validation checks */
5681 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5683 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5685 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5686 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5687 return D3DERR_INVALIDCALL;
5689 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5690 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5691 return D3DERR_INVALIDCALL;
5693 /* TODO: make the cursor 'real' */
5695 This->xHotSpot = XHotSpot;
5696 This->yHotSpot = YHotSpot;
5701 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5703 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5705 This->xScreenSpace = XScreenSpace;
5706 This->yScreenSpace = YScreenSpace;
5712 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5713 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5714 TRACE("(%p) : visible(%d)\n", This, bShow);
5716 This->bCursorVisible = bShow;
5721 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5723 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5728 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5730 /** FIXME: Resource tracking needs to be done,
5731 * The closes we can do to this is set the priorities of all managed textures low
5732 * and then reset them.
5733 ***********************************************************/
5734 FIXME("(%p) : stub\n", This);
5738 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5739 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5740 /** FIXME: Resource trascking needs to be done.
5741 * in effect this pulls all non only default
5742 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5743 * and should clear down the context and set it up according to pPresentationParameters
5744 ***********************************************************/
5745 FIXME("(%p) : stub\n", This);
5749 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5750 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5751 /** FIXME: always true at the moment **/
5752 if(bEnableDialogs == FALSE) {
5753 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5759 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5760 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5762 FIXME("(%p) : stub\n", This);
5763 /* Setup some reasonable defaults */
5764 pParameters->AdapterOrdinal = 0; /* always for now */
5765 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5766 pParameters->hFocusWindow = 0;
5767 pParameters->BehaviorFlags =0;
5771 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5772 IWineD3DSwapChain *swapchain;
5773 HRESULT hrc = D3D_OK;
5775 TRACE("Relaying to swapchain\n");
5777 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5778 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5779 IWineD3DSwapChain_Release(swapchain);
5784 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5785 IWineD3DSwapChain *swapchain;
5786 HRESULT hrc = D3D_OK;
5788 TRACE("Relaying to swapchain\n");
5790 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5791 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5792 IWineD3DSwapChain_Release(swapchain);
5798 /** ********************************************************
5799 * Notification functions
5800 ** ********************************************************/
5801 /** This function must be called in the release of a resource when ref == 0,
5802 * the contents of resource must still be correct,
5803 * any handels to other resource held by the caller must be closed
5804 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5805 *****************************************************/
5806 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5807 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5808 ResourceList* resourceList;
5810 TRACE("(%p) : resource %p\n", This, resource);
5812 EnterCriticalSection(&resourceStoreCriticalSection);
5814 /* add a new texture to the frot of the linked list */
5815 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5816 resourceList->resource = resource;
5818 /* Get the old head */
5819 resourceList->next = This->resources;
5821 This->resources = resourceList;
5822 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5825 LeaveCriticalSection(&resourceStoreCriticalSection);
5830 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5831 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5832 ResourceList* resourceList = NULL;
5833 ResourceList* previousResourceList = NULL;
5835 TRACE("(%p) : resource %p\n", This, resource);
5838 EnterCriticalSection(&resourceStoreCriticalSection);
5840 resourceList = This->resources;
5842 while (resourceList != NULL) {
5843 if(resourceList->resource == resource) break;
5844 previousResourceList = resourceList;
5845 resourceList = resourceList->next;
5848 if (resourceList == NULL) {
5849 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5851 LeaveCriticalSection(&resourceStoreCriticalSection);
5855 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5857 /* make sure we don't leave a hole in the list */
5858 if (previousResourceList != NULL) {
5859 previousResourceList->next = resourceList->next;
5861 This->resources = resourceList->next;
5865 LeaveCriticalSection(&resourceStoreCriticalSection);
5871 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5872 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5875 TRACE("(%p) : resource %p\n", This, resource);
5876 switch(IWineD3DResource_GetType(resource)){
5877 case D3DRTYPE_SURFACE:
5878 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5880 case D3DRTYPE_TEXTURE:
5881 case D3DRTYPE_CUBETEXTURE:
5882 case D3DRTYPE_VOLUMETEXTURE:
5883 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5884 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5885 IUnknown *textureParent;
5886 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5887 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5888 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5889 IUnknown_Release(textureParent);
5890 This->stateBlock->textures[counter] = NULL;
5892 if (This->updateStateBlock != This->stateBlock ){
5893 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5894 IUnknown *textureParent;
5895 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5896 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5897 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5898 IUnknown_Release(textureParent);
5899 This->updateStateBlock->textures[counter] = NULL;
5904 case D3DRTYPE_VOLUME:
5905 /* TODO: nothing really? */
5907 case D3DRTYPE_VERTEXBUFFER:
5908 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5911 TRACE("Cleaning up stream pointers\n");
5913 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5914 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5915 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5917 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5918 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5919 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5920 This->updateStateBlock->streamSource[streamNumber] = 0;
5921 /* Set changed flag? */
5924 if (This->stateBlock != NULL ) { /* only happens if their is an error in the application, or on reset/release (because we don't manage internal tracknig properly) */
5925 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5926 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5927 This->stateBlock->streamSource[streamNumber] = 0;
5930 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5931 else { /* This shouldn't happen */
5932 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5939 case D3DRTYPE_INDEXBUFFER:
5940 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5941 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5942 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5943 This->updateStateBlock->pIndexData = NULL;
5946 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5947 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5948 This->stateBlock->pIndexData = NULL;
5954 FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
5959 /* Remove the resoruce from the resourceStore */
5960 IWineD3DDeviceImpl_RemoveResource(iface, resource);
5962 TRACE("Resource released\n");
5967 /** This function is to be called by the swapchain when it is released and it's ref = 0
5968 *****************************************************/
5969 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
5970 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5971 SwapChainList **nextSwapchain;
5972 nextSwapchain = &This->swapchains;
5974 /* Check to see if the swapchian is being used as the render target */
5975 if (This->renderTarget != NULL) {
5976 IWineD3DSurface *swapchainBackBuffer;
5978 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
5979 if (This->renderTarget == swapchainBackBuffer) {
5980 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5981 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
5985 /* Go through the swapchain list and try to find the swapchain being released */
5986 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
5987 nextSwapchain = &(*nextSwapchain)->next;
5990 /* Check to see if we found the swapchain */
5991 if (NULL != *nextSwapchain) {
5992 /* We found the swapchain so remove it from the list */
5993 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
5994 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
5995 *nextSwapchain = (*nextSwapchain)->next;
5997 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
5998 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6001 TRACE("swapchain (%p) released\n", swapChain);
6005 /**********************************************************
6006 * IWineD3DDevice VTbl follows
6007 **********************************************************/
6009 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6011 /*** IUnknown methods ***/
6012 IWineD3DDeviceImpl_QueryInterface,
6013 IWineD3DDeviceImpl_AddRef,
6014 IWineD3DDeviceImpl_Release,
6015 /*** IWineD3DDevice methods ***/
6016 IWineD3DDeviceImpl_GetParent,
6017 /*** Creation methods**/
6018 IWineD3DDeviceImpl_CreateVertexBuffer,
6019 IWineD3DDeviceImpl_CreateIndexBuffer,
6020 IWineD3DDeviceImpl_CreateStateBlock,
6021 IWineD3DDeviceImpl_CreateSurface,
6022 IWineD3DDeviceImpl_CreateTexture,
6023 IWineD3DDeviceImpl_CreateVolumeTexture,
6024 IWineD3DDeviceImpl_CreateVolume,
6025 IWineD3DDeviceImpl_CreateCubeTexture,
6026 IWineD3DDeviceImpl_CreateQuery,
6027 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6028 IWineD3DDeviceImpl_CreateVertexDeclaration,
6029 IWineD3DDeviceImpl_CreateVertexShader,
6030 IWineD3DDeviceImpl_CreatePixelShader,
6032 /*** Odd functions **/
6033 IWineD3DDeviceImpl_EvictManagedResources,
6034 IWineD3DDeviceImpl_GetAvailableTextureMem,
6035 IWineD3DDeviceImpl_GetBackBuffer,
6036 IWineD3DDeviceImpl_GetCreationParameters,
6037 IWineD3DDeviceImpl_GetDeviceCaps,
6038 IWineD3DDeviceImpl_GetDirect3D,
6039 IWineD3DDeviceImpl_GetDisplayMode,
6040 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6041 IWineD3DDeviceImpl_GetRasterStatus,
6042 IWineD3DDeviceImpl_GetSwapChain,
6043 IWineD3DDeviceImpl_Reset,
6044 IWineD3DDeviceImpl_SetDialogBoxMode,
6045 IWineD3DDeviceImpl_SetCursorProperties,
6046 IWineD3DDeviceImpl_SetCursorPosition,
6047 IWineD3DDeviceImpl_ShowCursor,
6048 IWineD3DDeviceImpl_TestCooperativeLevel,
6049 /*** Getters and setters **/
6050 IWineD3DDeviceImpl_SetClipPlane,
6051 IWineD3DDeviceImpl_GetClipPlane,
6052 IWineD3DDeviceImpl_SetClipStatus,
6053 IWineD3DDeviceImpl_GetClipStatus,
6054 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6055 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6056 IWineD3DDeviceImpl_SetDepthStencilSurface,
6057 IWineD3DDeviceImpl_GetDepthStencilSurface,
6058 IWineD3DDeviceImpl_SetFVF,
6059 IWineD3DDeviceImpl_GetFVF,
6060 IWineD3DDeviceImpl_SetGammaRamp,
6061 IWineD3DDeviceImpl_GetGammaRamp,
6062 IWineD3DDeviceImpl_SetIndices,
6063 IWineD3DDeviceImpl_GetIndices,
6064 IWineD3DDeviceImpl_SetLight,
6065 IWineD3DDeviceImpl_GetLight,
6066 IWineD3DDeviceImpl_SetLightEnable,
6067 IWineD3DDeviceImpl_GetLightEnable,
6068 IWineD3DDeviceImpl_SetMaterial,
6069 IWineD3DDeviceImpl_GetMaterial,
6070 IWineD3DDeviceImpl_SetNPatchMode,
6071 IWineD3DDeviceImpl_GetNPatchMode,
6072 IWineD3DDeviceImpl_SetPaletteEntries,
6073 IWineD3DDeviceImpl_GetPaletteEntries,
6074 IWineD3DDeviceImpl_SetPixelShader,
6075 IWineD3DDeviceImpl_GetPixelShader,
6076 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6077 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6078 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6079 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6080 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6081 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6082 IWineD3DDeviceImpl_SetRenderState,
6083 IWineD3DDeviceImpl_GetRenderState,
6084 IWineD3DDeviceImpl_SetRenderTarget,
6085 IWineD3DDeviceImpl_GetRenderTarget,
6086 IWineD3DDeviceImpl_SetSamplerState,
6087 IWineD3DDeviceImpl_GetSamplerState,
6088 IWineD3DDeviceImpl_SetScissorRect,
6089 IWineD3DDeviceImpl_GetScissorRect,
6090 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6091 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6092 IWineD3DDeviceImpl_SetStreamSource,
6093 IWineD3DDeviceImpl_GetStreamSource,
6094 IWineD3DDeviceImpl_SetStreamSourceFreq,
6095 IWineD3DDeviceImpl_GetStreamSourceFreq,
6096 IWineD3DDeviceImpl_SetTexture,
6097 IWineD3DDeviceImpl_GetTexture,
6098 IWineD3DDeviceImpl_SetTextureStageState,
6099 IWineD3DDeviceImpl_GetTextureStageState,
6100 IWineD3DDeviceImpl_SetTransform,
6101 IWineD3DDeviceImpl_GetTransform,
6102 IWineD3DDeviceImpl_SetVertexDeclaration,
6103 IWineD3DDeviceImpl_GetVertexDeclaration,
6104 IWineD3DDeviceImpl_SetVertexShader,
6105 IWineD3DDeviceImpl_GetVertexShader,
6106 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6107 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6108 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6109 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6110 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6111 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6112 IWineD3DDeviceImpl_SetViewport,
6113 IWineD3DDeviceImpl_GetViewport,
6114 IWineD3DDeviceImpl_MultiplyTransform,
6115 IWineD3DDeviceImpl_ValidateDevice,
6116 IWineD3DDeviceImpl_ProcessVertices,
6117 /*** State block ***/
6118 IWineD3DDeviceImpl_BeginStateBlock,
6119 IWineD3DDeviceImpl_EndStateBlock,
6120 /*** Scene management ***/
6121 IWineD3DDeviceImpl_BeginScene,
6122 IWineD3DDeviceImpl_EndScene,
6123 IWineD3DDeviceImpl_Present,
6124 IWineD3DDeviceImpl_Clear,
6126 IWineD3DDeviceImpl_DrawPrimitive,
6127 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6128 IWineD3DDeviceImpl_DrawPrimitiveUP,
6129 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6130 IWineD3DDeviceImpl_DrawRectPatch,
6131 IWineD3DDeviceImpl_DrawTriPatch,
6132 IWineD3DDeviceImpl_DeletePatch,
6133 IWineD3DDeviceImpl_ColorFill,
6134 IWineD3DDeviceImpl_UpdateTexture,
6135 IWineD3DDeviceImpl_UpdateSurface,
6136 IWineD3DDeviceImpl_StretchRect,
6137 IWineD3DDeviceImpl_GetRenderTargetData,
6138 IWineD3DDeviceImpl_GetFrontBufferData,
6139 /*** Internal use IWineD3DDevice methods ***/
6140 IWineD3DDeviceImpl_SetupTextureStates,
6141 IWineD3DDeviceImpl_SwapChainReleased,
6142 /*** object tracking ***/
6143 IWineD3DDeviceImpl_ResourceReleased
6147 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6148 WINED3DRS_ALPHABLENDENABLE ,
6149 WINED3DRS_ALPHAFUNC ,
6150 WINED3DRS_ALPHAREF ,
6151 WINED3DRS_ALPHATESTENABLE ,
6153 WINED3DRS_COLORWRITEENABLE ,
6154 WINED3DRS_DESTBLEND ,
6155 WINED3DRS_DITHERENABLE ,
6156 WINED3DRS_FILLMODE ,
6157 WINED3DRS_FOGDENSITY ,
6159 WINED3DRS_FOGSTART ,
6160 WINED3DRS_LASTPIXEL ,
6161 WINED3DRS_SHADEMODE ,
6162 WINED3DRS_SRCBLEND ,
6163 WINED3DRS_STENCILENABLE ,
6164 WINED3DRS_STENCILFAIL ,
6165 WINED3DRS_STENCILFUNC ,
6166 WINED3DRS_STENCILMASK ,
6167 WINED3DRS_STENCILPASS ,
6168 WINED3DRS_STENCILREF ,
6169 WINED3DRS_STENCILWRITEMASK ,
6170 WINED3DRS_STENCILZFAIL ,
6171 WINED3DRS_TEXTUREFACTOR ,
6182 WINED3DRS_ZWRITEENABLE
6185 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6186 WINED3DTSS_ADDRESSW ,
6187 WINED3DTSS_ALPHAARG0 ,
6188 WINED3DTSS_ALPHAARG1 ,
6189 WINED3DTSS_ALPHAARG2 ,
6190 WINED3DTSS_ALPHAOP ,
6191 WINED3DTSS_BUMPENVLOFFSET ,
6192 WINED3DTSS_BUMPENVLSCALE ,
6193 WINED3DTSS_BUMPENVMAT00 ,
6194 WINED3DTSS_BUMPENVMAT01 ,
6195 WINED3DTSS_BUMPENVMAT10 ,
6196 WINED3DTSS_BUMPENVMAT11 ,
6197 WINED3DTSS_COLORARG0 ,
6198 WINED3DTSS_COLORARG1 ,
6199 WINED3DTSS_COLORARG2 ,
6200 WINED3DTSS_COLOROP ,
6201 WINED3DTSS_RESULTARG ,
6202 WINED3DTSS_TEXCOORDINDEX ,
6203 WINED3DTSS_TEXTURETRANSFORMFLAGS
6206 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6207 WINED3DSAMP_ADDRESSU ,
6208 WINED3DSAMP_ADDRESSV ,
6209 WINED3DSAMP_ADDRESSW ,
6210 WINED3DSAMP_BORDERCOLOR ,
6211 WINED3DSAMP_MAGFILTER ,
6212 WINED3DSAMP_MINFILTER ,
6213 WINED3DSAMP_MIPFILTER ,
6214 WINED3DSAMP_MIPMAPLODBIAS ,
6215 WINED3DSAMP_MAXMIPLEVEL ,
6216 WINED3DSAMP_MAXANISOTROPY ,
6217 WINED3DSAMP_SRGBTEXTURE ,
6218 WINED3DSAMP_ELEMENTINDEX
6221 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6223 WINED3DRS_AMBIENTMATERIALSOURCE ,
6224 WINED3DRS_CLIPPING ,
6225 WINED3DRS_CLIPPLANEENABLE ,
6226 WINED3DRS_COLORVERTEX ,
6227 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6228 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6229 WINED3DRS_FOGDENSITY ,
6231 WINED3DRS_FOGSTART ,
6232 WINED3DRS_FOGTABLEMODE ,
6233 WINED3DRS_FOGVERTEXMODE ,
6234 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6235 WINED3DRS_LIGHTING ,
6236 WINED3DRS_LOCALVIEWER ,
6237 WINED3DRS_MULTISAMPLEANTIALIAS ,
6238 WINED3DRS_MULTISAMPLEMASK ,
6239 WINED3DRS_NORMALIZENORMALS ,
6240 WINED3DRS_PATCHEDGESTYLE ,
6241 WINED3DRS_POINTSCALE_A ,
6242 WINED3DRS_POINTSCALE_B ,
6243 WINED3DRS_POINTSCALE_C ,
6244 WINED3DRS_POINTSCALEENABLE ,
6245 WINED3DRS_POINTSIZE ,
6246 WINED3DRS_POINTSIZE_MAX ,
6247 WINED3DRS_POINTSIZE_MIN ,
6248 WINED3DRS_POINTSPRITEENABLE ,
6249 WINED3DRS_RANGEFOGENABLE ,
6250 WINED3DRS_SPECULARMATERIALSOURCE ,
6251 WINED3DRS_TWEENFACTOR ,
6252 WINED3DRS_VERTEXBLEND
6255 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6256 WINED3DTSS_TEXCOORDINDEX ,
6257 WINED3DTSS_TEXTURETRANSFORMFLAGS
6260 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6261 WINED3DSAMP_DMAPOFFSET