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 /** FIXME: Check that the format is supported
596 *******************************/
597 /* TODO: add support for dxt2 and dxt4 formats */
598 if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT4) return D3DERR_NOTAVAILABLE;
600 /* Non-power2 support */
602 /* Find the nearest pow2 match */
603 pow2Width = pow2Height = 1;
604 while (pow2Width < Width) pow2Width <<= 1;
605 while (pow2Height < Height) pow2Height <<= 1;
607 if (pow2Width > Width || pow2Height > Height) {
608 /** TODO: add support for non power two compressed textures (OpenGL 2 provices support for * non-power-two textures gratis) **/
609 if (Format == WINED3DFMT_DXT1 || Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3
610 || Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
611 FIXME("(%p) Compressed non-power-two textures are not supported w(%d) h(%d) \n",
612 This, Width, Height);
613 return D3DERR_NOTAVAILABLE;
617 /** Check against the maximum texture sizes supported by the video card **/
618 if (pow2Width > GL_LIMITS(texture_size) || pow2Height > GL_LIMITS(texture_size)) {
619 /* one of three options
620 1: Do the same as we do with nonpow 2 and scale the texture, (any texture ops would require the texture to be scaled which is potentially slow)
621 2: Set the texture to the maxium size (bad idea)
622 3: WARN and return D3DERR_NOTAVAILABLE;
624 WARN("(%p) Application requested a surface w %d, h %d, but the graphics card only supports %d\n", This, Width, Height, GL_LIMITS(texture_size));
625 return D3DERR_NOTAVAILABLE;
630 /** DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
631 * it is based around 4x4 pixel blocks it requires padding, so allocate enough
633 *********************************/
634 if (Format == WINED3DFMT_DXT1) {
635 /* DXT1 is half byte per pixel */
636 Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4)) >> 1;
638 } else if (Format == WINED3DFMT_DXT2 || Format == WINED3DFMT_DXT3 ||
639 Format == WINED3DFMT_DXT4 || Format == WINED3DFMT_DXT5) {
640 Size = ((max(Width,4) * D3DFmtGetBpp(This, Format)) * max(Height,4));
642 Size = (Width * D3DFmtGetBpp(This, Format)) * Height;
645 /** Create the and initilise surface resource **/
646 D3DCREATERESOURCEOBJECTINSTANCE(object,Surface,D3DRTYPE_SURFACE, Size)
647 object->container = (IUnknown*) This;
649 object->currentDesc.Width = Width;
650 object->currentDesc.Height = Height;
651 object->currentDesc.MultiSampleType = MultiSample;
652 object->currentDesc.MultiSampleQuality = MultisampleQuality;
654 /* Setup some glformat defaults */
655 object->glDescription.glFormat = D3DFmt2GLFmt(This, object->resource.format);
656 object->glDescription.glFormatInternal = D3DFmt2GLIntFmt(This, object->resource.format);
657 object->glDescription.glType = D3DFmt2GLType(This, object->resource.format);
658 object->glDescription.textureName = 0;
659 object->glDescription.level = Level;
660 object->glDescription.target = GL_TEXTURE_2D;
663 object->pow2Width = pow2Width;
664 object->pow2Height = pow2Height;
665 object->nonpow2 = (pow2Width != Width || pow2Height != Height) ? TRUE : FALSE;
666 object->discard = Discard;
667 object->activeLock = FALSE;
668 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
669 object->pow2Size = (pow2Width * object->bytesPerPixel) * pow2Height;
671 /** TODO: change this into a texture transform matrix so that it's processed in hardware **/
673 /* Precalculated scaling for 'faked' non power of two texture coords */
674 object->pow2scalingFactorX = (((float)Width) / ((float)pow2Width));
675 object->pow2scalingFactorY = (((float)Height) / ((float)pow2Height));
676 TRACE(" xf(%f) yf(%f) \n", object->pow2scalingFactorX, object->pow2scalingFactorY);
678 TRACE("Pool %d %d %d %d",Pool, D3DPOOL_DEFAULT, D3DPOOL_MANAGED, D3DPOOL_SYSTEMMEM);
680 /** Quick lockable sanity check TODO: remove this after surfaces, usage and locablility have been debugged properly
681 * this function is too deap to need to care about things like this.
682 * Levels need to be checked too, and possibly Type wince they all affect what can be done.
683 * ****************************************/
685 case D3DPOOL_SCRATCH:
686 if(Lockable == FALSE)
687 FIXME("Create suface called with a pool of SCRATCH and a Lockable of FALSE \
688 which are mutually exclusive, setting lockable to true\n");
691 case D3DPOOL_SYSTEMMEM:
692 if(Lockable == FALSE) FIXME("Create surface called with a pool of SYSTEMMEM and a Lockable of FALSE, \
693 this is acceptable but unexpected (I can't know how the surface can be usable!)\n");
694 case D3DPOOL_MANAGED:
695 if(Usage == D3DUSAGE_DYNAMIC) FIXME("Create surface called with a pool of MANAGED and a \
696 Usage of DYNAMIC which are mutually exclusive, not doing \
697 anything just telling you.\n");
699 case D3DPOOL_DEFAULT: /*TODO: Create offscreen plain can cause this check to fail..., find out if it should */
700 if(!(Usage & D3DUSAGE_DYNAMIC) && !(Usage & D3DUSAGE_RENDERTARGET)
701 && !(Usage && D3DUSAGE_DEPTHSTENCIL ) && Lockable == TRUE)
702 FIXME("Creating a surface with a POOL of DEFAULT with Locable true, that doesn't specify DYNAMIC usage.\n");
705 FIXME("(%p) Unknown pool %d\n", This, Pool);
709 if (Usage & D3DUSAGE_RENDERTARGET && Pool != D3DPOOL_DEFAULT) {
710 FIXME("Trying to create a render target that isn't in the default pool\n");
714 object->locked = FALSE;
715 object->lockable = (WINED3DFMT_D16_LOCKABLE == Format) ? TRUE : Lockable;
717 /* mark the texture as dirty so that it get's loaded first time around*/
718 IWineD3DSurface_AddDirtyRect(*ppSurface, NULL);
719 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n",
720 This, Width, Height, Format, debug_d3dformat(Format),
721 (WINED3DFMT_D16_LOCKABLE == Format), *ppSurface, object->resource.allocatedMemory, object->resource.size);
726 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width, UINT Height, UINT Levels,
727 DWORD Usage, WINED3DFORMAT Format, D3DPOOL Pool,
728 IWineD3DTexture** ppTexture, HANDLE* pSharedHandle, IUnknown *parent,
729 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
731 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
732 IWineD3DTextureImpl *object;
738 TRACE("(%p), Width(%d) Height(%d) Levels(%d) Usage(%ld) .... \n", This, Width, Height, Levels, Usage);
740 D3DCREATERESOURCEOBJECTINSTANCE(object, Texture, D3DRTYPE_TEXTURE, 0);
741 D3DINITILIZEBASETEXTURE(object->baseTexture);
742 object->width = Width;
743 object->height = Height;
745 /* Calculate levels for mip mapping */
747 TRACE("calculating levels %d\n", object->baseTexture.levels);
748 object->baseTexture.levels++;
751 while (tmpW > 1 && tmpH > 1) {
752 tmpW = max(1, tmpW >> 1);
753 tmpH = max(1, tmpH >> 1);
754 object->baseTexture.levels++;
756 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
759 /* Generate all the surfaces */
762 for (i = 0; i < object->baseTexture.levels; i++)
764 /* use the callback to create the texture surface */
765 hr = D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Usage, Pool, i, &object->surfaces[i],NULL);
768 FIXME("Failed to create surface %p \n",object);
770 for(j = 0 ; j < i ; j++) {
771 IWineD3DSurface_Release(object->surfaces[j]);
773 /* heap free object */
774 HeapFree(GetProcessHeap(),0,object);
780 IWineD3DSurface_SetContainer(object->surfaces[i], (IUnknown *)object);
781 TRACE("Created surface level %d @ %p\n", i, object->surfaces[i]);
782 /* calculate the next mipmap level */
783 tmpW = max(1, tmpW >> 1);
784 tmpH = max(1, tmpH >> 1);
787 TRACE("(%p) : Created texture %p\n", This, object);
791 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
792 UINT Width, UINT Height, UINT Depth,
793 UINT Levels, DWORD Usage,
794 WINED3DFORMAT Format, D3DPOOL Pool,
795 IWineD3DVolumeTexture** ppVolumeTexture,
796 HANDLE* pSharedHandle, IUnknown *parent,
797 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
799 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
800 IWineD3DVolumeTextureImpl *object;
806 D3DCREATERESOURCEOBJECTINSTANCE(object, VolumeTexture, D3DRTYPE_VOLUMETEXTURE, 0);
807 D3DINITILIZEBASETEXTURE(object->baseTexture);
809 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
810 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
812 object->width = Width;
813 object->height = Height;
814 object->depth = Depth;
816 /* Calculate levels for mip mapping */
818 object->baseTexture.levels++;
822 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
823 tmpW = max(1, tmpW >> 1);
824 tmpH = max(1, tmpH >> 1);
825 tmpD = max(1, tmpD >> 1);
826 object->baseTexture.levels++;
828 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
831 /* Generate all the surfaces */
836 for (i = 0; i < object->baseTexture.levels; i++)
838 /* Create the volume */
839 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
840 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
841 IWineD3DVolume_SetContainer(object->volumes[i], (IUnknown *)object);
843 tmpW = max(1, tmpW >> 1);
844 tmpH = max(1, tmpH >> 1);
845 tmpD = max(1, tmpD >> 1);
848 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
849 TRACE("(%p) : Created volume texture %p\n", This, object);
853 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
854 UINT Width, UINT Height, UINT Depth,
856 WINED3DFORMAT Format, D3DPOOL Pool,
857 IWineD3DVolume** ppVolume,
858 HANDLE* pSharedHandle, IUnknown *parent) {
860 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
861 IWineD3DVolumeImpl *object; /** NOTE: impl ref allowed since this is a create function **/
863 D3DCREATERESOURCEOBJECTINSTANCE(object, Volume, D3DRTYPE_VOLUME, ((Width * D3DFmtGetBpp(This, Format)) * Height * Depth))
865 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
866 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
868 object->currentDesc.Width = Width;
869 object->currentDesc.Height = Height;
870 object->currentDesc.Depth = Depth;
871 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
873 /** Note: Volume textures cannot be dxtn, hence no need to check here **/
874 object->lockable = TRUE;
875 object->locked = FALSE;
876 memset(&object->lockedBox, 0, sizeof(D3DBOX));
877 object->dirty = FALSE;
878 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
881 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
882 UINT Levels, DWORD Usage,
883 WINED3DFORMAT Format, D3DPOOL Pool,
884 IWineD3DCubeTexture** ppCubeTexture,
885 HANDLE* pSharedHandle, IUnknown *parent,
886 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
888 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
889 IWineD3DCubeTextureImpl *object; /** NOTE: impl ref allowed since this is a create function **/
894 D3DCREATERESOURCEOBJECTINSTANCE(object, CubeTexture, D3DRTYPE_CUBETEXTURE, 0);
895 D3DINITILIZEBASETEXTURE(object->baseTexture);
897 TRACE("(%p) Create Cube Texture \n", This);
899 object->edgeLength = EdgeLength;
901 /* Calculate levels for mip mapping */
903 object->baseTexture.levels++;
906 tmpW = max(1, tmpW / 2);
907 object->baseTexture.levels++;
909 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
912 /* Generate all the surfaces */
914 for (i = 0; i < object->baseTexture.levels; i++) {
916 /* Create the 6 faces */
917 for (j = 0; j < 6; j++) {
919 hr=D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Usage, Pool,
920 i /* Level */, &object->surfaces[j][i],pSharedHandle);
927 IWineD3DSurface_Release(object->surfaces[j][i]);
931 IWineD3DSurface_Release(object->surfaces[l][j]);
935 FIXME("(%p) Failed to create surface\n",object);
936 HeapFree(GetProcessHeap(),0,object);
937 *ppCubeTexture = NULL;
940 IWineD3DSurface_SetContainer(object->surfaces[j][i], (IUnknown *)object);
941 TRACE("Created surface level %d @ %p, \n", i, object->surfaces[j][i]);
943 tmpW = max(1, tmpW >> 1);
946 TRACE("(%p) : Created Cube Texture %p\n", This, object);
947 *ppCubeTexture = (IWineD3DCubeTexture *) object;
951 HRESULT WINAPI IWineD3DDeviceImpl_CreateQuery(IWineD3DDevice *iface, WINED3DQUERYTYPE Type, IWineD3DQuery **ppQuery, IUnknown* parent) {
952 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
953 IWineD3DQueryImpl *object; /*NOTE: impl ref allowed since this is a create function */
955 if(NULL == ppQuery) {
956 /* Just a check to see if we support this type of query */
957 HRESULT hr = D3DERR_NOTAVAILABLE;
958 /* Lie and say everything is good (we can return ok fake data from a stub) */
960 case WINED3DQUERYTYPE_VCACHE:
961 case WINED3DQUERYTYPE_RESOURCEMANAGER:
962 case WINED3DQUERYTYPE_VERTEXSTATS:
963 case WINED3DQUERYTYPE_EVENT:
964 case WINED3DQUERYTYPE_OCCLUSION:
965 case WINED3DQUERYTYPE_TIMESTAMP:
966 case WINED3DQUERYTYPE_TIMESTAMPDISJOINT:
967 case WINED3DQUERYTYPE_TIMESTAMPFREQ:
968 case WINED3DQUERYTYPE_PIPELINETIMINGS:
969 case WINED3DQUERYTYPE_INTERFACETIMINGS:
970 case WINED3DQUERYTYPE_VERTEXTIMINGS:
971 case WINED3DQUERYTYPE_PIXELTIMINGS:
972 case WINED3DQUERYTYPE_BANDWIDTHTIMINGS:
973 case WINED3DQUERYTYPE_CACHEUTILIZATION:
977 FIXME("(%p) Unhandled query type %d\n",This , Type);
979 FIXME("(%p) : Stub request for query type %d returned %ld\n", This, Type, hr);
983 D3DCREATEOBJECTINSTANCE(object, Query)
985 object->extendedData = 0;
986 TRACE("(%p) : Created Query %p\n", This, object);
990 /* example at http://www.fairyengine.com/articles/dxmultiviews.htm */
991 HRESULT WINAPI IWineD3DDeviceImpl_CreateAdditionalSwapChain(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters, IWineD3DSwapChain** ppSwapChain,
993 D3DCB_CREATERENDERTARGETFN D3DCB_CreateRenderTarget,
994 D3DCB_CREATEDEPTHSTENCILSURFACEFN D3DCB_CreateDepthStencil) {
995 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
998 IWineD3DSwapChainImpl *object; /** NOTE: impl ref allowed since this is a create function **/
1000 XVisualInfo template;
1001 GLXContext oldContext;
1002 Drawable oldDrawable;
1003 HRESULT hr = D3D_OK;
1005 TRACE("(%p) : Created Aditional Swap Chain\n", This);
1007 /** FIXME: Test under windows to find out what the life cycle of a swap chain is,
1008 * does a device hold a reference to a swap chain giving them a lifetime of the device
1009 * or does the swap chain notify the device of it'd destruction.
1010 *******************************/
1012 D3DCREATEOBJECTINSTANCE(object, SwapChain)
1014 /* Initialize other useful values */
1015 object->presentParms.BackBufferCount = 1; /* TODO:? support for gl_aux buffers */
1017 /*********************
1018 * Lookup the window Handle and the relating X window handle
1019 ********************/
1021 /* Setup hwnd we are using, plus which display this equates to */
1022 object->win_handle = *(pPresentationParameters->hDeviceWindow);
1023 if (!object->win_handle) {
1024 object->win_handle = This->createParms.hFocusWindow;
1027 object->win = (Window)GetPropA(object->win_handle, "__wine_x11_whole_window" );
1028 hDc = GetDC(object->win_handle);
1029 object->display = get_display(hDc);
1030 ReleaseDC(object->win_handle, hDc);
1031 TRACE("Using a display of %p %p \n", object->display, hDc);
1033 if (NULL == object->display || NULL == hDc) {
1034 WARN("Failed to get a display and HDc for Window %p\n", object->win_handle);
1035 return D3DERR_NOTAVAILABLE;
1038 if (object->win == 0) {
1039 WARN("Failed to get a valid XVisuial ID for the window %p\n", object->win_handle);
1040 return D3DERR_NOTAVAILABLE;
1043 * Create an opengl context for the display visual
1044 * NOTE: the visual is chosen as the window is created and the glcontext cannot
1045 * use different properties after that point in time. FIXME: How to handle when requested format
1046 * doesn't match actual visual? Cannot choose one here - code removed as it ONLY works if the one
1047 * it chooses is identical to the one already being used!
1048 **********************************/
1050 /** FIXME: Handle stencil appropriately via EnableAutoDepthStencil / AutoDepthStencilFormat **/
1053 /* Create a new context for this swapchain */
1054 template.visualid = (VisualID)GetPropA(GetDesktopWindow(), "__wine_x11_visual_id");
1055 /* TODO: change this to find a similar visual, but one with a stencil/zbuffer buffer that matches the request
1056 (or the best possible if none is requested) */
1057 TRACE("Found x visual ID : %ld\n", template.visualid);
1059 object->visInfo = XGetVisualInfo(object->display, VisualIDMask, &template, &num);
1060 if (NULL == object->visInfo) {
1061 ERR("cannot really get XVisual\n");
1063 return D3DERR_NOTAVAILABLE;
1066 /* Write out some debug info about the visual/s */
1067 TRACE("Using x visual ID : %ld\n", template.visualid);
1068 TRACE(" visual info: %p\n", object->visInfo);
1069 TRACE(" num items : %d\n", num);
1070 for(n = 0;n < num; n++) {
1071 TRACE("=====item=====: %d\n", n + 1);
1072 TRACE(" visualid : %ld\n", object->visInfo[n].visualid);
1073 TRACE(" screen : %d\n", object->visInfo[n].screen);
1074 TRACE(" depth : %u\n", object->visInfo[n].depth);
1075 TRACE(" class : %d\n", object->visInfo[n].class);
1076 TRACE(" red_mask : %ld\n", object->visInfo[n].red_mask);
1077 TRACE(" green_mask : %ld\n", object->visInfo[n].green_mask);
1078 TRACE(" blue_mask : %ld\n", object->visInfo[n].blue_mask);
1079 TRACE(" colormap_size : %d\n", object->visInfo[n].colormap_size);
1080 TRACE(" bits_per_rgb : %d\n", object->visInfo[n].bits_per_rgb);
1081 /* log some extra glx info */
1082 glXGetConfig(object->display, object->visInfo, GLX_AUX_BUFFERS, &value);
1083 TRACE(" gl_aux_buffers : %d\n", value);
1084 glXGetConfig(object->display, object->visInfo, GLX_BUFFER_SIZE ,&value);
1085 TRACE(" gl_buffer_size : %d\n", value);
1086 glXGetConfig(object->display, object->visInfo, GLX_RED_SIZE, &value);
1087 TRACE(" gl_red_size : %d\n", value);
1088 glXGetConfig(object->display, object->visInfo, GLX_GREEN_SIZE, &value);
1089 TRACE(" gl_green_size : %d\n", value);
1090 glXGetConfig(object->display, object->visInfo, GLX_BLUE_SIZE, &value);
1091 TRACE(" gl_blue_size : %d\n", value);
1092 glXGetConfig(object->display, object->visInfo, GLX_ALPHA_SIZE, &value);
1093 TRACE(" gl_alpha_size : %d\n", value);
1094 glXGetConfig(object->display, object->visInfo, GLX_DEPTH_SIZE ,&value);
1095 TRACE(" gl_depth_size : %d\n", value);
1096 glXGetConfig(object->display, object->visInfo, GLX_STENCIL_SIZE, &value);
1097 TRACE(" gl_stencil_size : %d\n", value);
1099 /* Now choose a simila visual ID*/
1101 #ifdef USE_CONTEXT_MANAGER
1103 /** TODO: use a context mamager **/
1107 IWineD3DSwapChain *implSwapChain;
1108 if (D3D_OK != IWineD3DDevice_GetSwapChain(iface, 0, &implSwapChain)) {
1109 /* The first time around we create the context that is shared with all other swapchains and render targets */
1110 object->glCtx = glXCreateContext(object->display, object->visInfo, NULL, GL_TRUE);
1111 TRACE("Creating implicit context for vis %p, hwnd %p\n", object->display, object->visInfo);
1114 TRACE("Creating context for vis %p, hwnd %p\n", object->display, object->visInfo);
1115 /* TODO: don't use Impl structures outside of create functions! (a context manager will replace the ->glCtx) */
1116 /* and create a new context with the implicit swapchains context as the shared context */
1117 object->glCtx = glXCreateContext(object->display, object->visInfo, ((IWineD3DSwapChainImpl *)implSwapChain)->glCtx, GL_TRUE);
1118 IWineD3DSwapChain_Release(implSwapChain);
1123 XFree(object->visInfo);
1124 object->visInfo = NULL;
1126 if (NULL == object->glCtx) {
1127 ERR("cannot create glxContext\n");
1129 return D3DERR_NOTAVAILABLE;
1133 if (object->glCtx == NULL) {
1134 ERR("Error in context creation !\n");
1135 return D3DERR_INVALIDCALL;
1137 TRACE("Context created (HWND=%p, glContext=%p, Window=%ld, VisInfo=%p)\n",
1138 object->win_handle, object->glCtx, object->win, object->visInfo);
1141 /*********************
1142 * Windowed / Fullscreen
1143 *******************/
1146 * TODO: MSDN says that we are only allowed one fullscreen swapchain per device,
1147 * so we should really check to see if their is a fullscreen swapchain already
1148 * I think Windows and X have different ideas about fullscreen, does a single head count as full screen?
1149 **************************************/
1151 if (!*(pPresentationParameters->Windowed)) {
1157 /* Get info on the current display setup */
1158 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
1159 bpp = GetDeviceCaps(hdc, BITSPIXEL);
1162 /* Change the display settings */
1163 memset(&devmode, 0, sizeof(DEVMODEW));
1164 devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
1165 devmode.dmBitsPerPel = (bpp >= 24) ? 32 : bpp; /* Stupid XVidMode cannot change bpp */
1166 devmode.dmPelsWidth = *(pPresentationParameters->BackBufferWidth);
1167 devmode.dmPelsHeight = *(pPresentationParameters->BackBufferHeight);
1168 MultiByteToWideChar(CP_ACP, 0, "Gamers CG", -1, devmode.dmDeviceName, CCHDEVICENAME);
1169 ChangeDisplaySettingsExW(devmode.dmDeviceName, &devmode, object->win_handle, CDS_FULLSCREEN, NULL);
1171 /* Make popup window */
1172 SetWindowLongA(object->win_handle, GWL_STYLE, WS_POPUP);
1173 SetWindowPos(object->win_handle, HWND_TOP, 0, 0,
1174 *(pPresentationParameters->BackBufferWidth),
1175 *(pPresentationParameters->BackBufferHeight), SWP_SHOWWINDOW | SWP_FRAMECHANGED);
1181 /** MSDN: If Windowed is TRUE and either of the BackBufferWidth/Height values is zero,
1182 * then the corresponding dimension of the client area of the hDeviceWindow
1183 * (or the focus window, if hDeviceWindow is NULL) is taken.
1184 **********************/
1186 if (*(pPresentationParameters->Windowed) &&
1187 ((*(pPresentationParameters->BackBufferWidth) == 0) ||
1188 (*(pPresentationParameters->BackBufferHeight) == 0))) {
1191 GetClientRect(object->win_handle, &Rect);
1193 if (*(pPresentationParameters->BackBufferWidth) == 0) {
1194 *(pPresentationParameters->BackBufferWidth) = Rect.right;
1195 TRACE("Updating width to %d\n", *(pPresentationParameters->BackBufferWidth));
1197 if (*(pPresentationParameters->BackBufferHeight) == 0) {
1198 *(pPresentationParameters->BackBufferHeight) = Rect.bottom;
1199 TRACE("Updating height to %d\n", *(pPresentationParameters->BackBufferHeight));
1203 /*********************
1204 * finish off parameter initialization
1205 *******************/
1207 /* Put the correct figures in the presentation parameters */
1208 TRACE("Coppying accross presentaion paraneters\n");
1209 object->presentParms.BackBufferWidth = *(pPresentationParameters->BackBufferWidth);
1210 object->presentParms.BackBufferHeight = *(pPresentationParameters->BackBufferHeight);
1211 object->presentParms.BackBufferFormat = *(pPresentationParameters->BackBufferFormat);
1212 object->presentParms.BackBufferCount = *(pPresentationParameters->BackBufferCount);
1213 object->presentParms.MultiSampleType = *(pPresentationParameters->MultiSampleType);
1214 object->presentParms.MultiSampleQuality = *(pPresentationParameters->MultiSampleQuality);
1215 object->presentParms.SwapEffect = *(pPresentationParameters->SwapEffect);
1216 object->presentParms.hDeviceWindow = *(pPresentationParameters->hDeviceWindow);
1217 object->presentParms.Windowed = *(pPresentationParameters->Windowed);
1218 object->presentParms.EnableAutoDepthStencil = *(pPresentationParameters->EnableAutoDepthStencil);
1219 object->presentParms.AutoDepthStencilFormat = *(pPresentationParameters->AutoDepthStencilFormat);
1220 object->presentParms.Flags = *(pPresentationParameters->Flags);
1221 object->presentParms.FullScreen_RefreshRateInHz = *(pPresentationParameters->FullScreen_RefreshRateInHz);
1222 object->presentParms.PresentationInterval = *(pPresentationParameters->PresentationInterval);
1225 /*********************
1226 * Create the back, front and stencil buffers
1227 *******************/
1228 TRACE("calling rendertarget CB\n");
1229 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1230 object->presentParms.BackBufferWidth,
1231 object->presentParms.BackBufferHeight,
1232 object->presentParms.BackBufferFormat,
1233 object->presentParms.MultiSampleType,
1234 object->presentParms.MultiSampleQuality,
1235 TRUE /* Lockable */,
1236 &object->frontBuffer,
1237 NULL /* pShared (always null)*/);
1238 if (object->frontBuffer != NULL)
1239 IWineD3DSurface_SetContainer(object->frontBuffer, (IUnknown *)object);
1240 TRACE("calling rendertarget CB\n");
1241 hr = D3DCB_CreateRenderTarget((IUnknown *) This->parent,
1242 object->presentParms.BackBufferWidth,
1243 object->presentParms.BackBufferHeight,
1244 object->presentParms.BackBufferFormat,
1245 object->presentParms.MultiSampleType,
1246 object->presentParms.MultiSampleQuality,
1247 TRUE /* Lockable */,
1248 &object->backBuffer,
1249 NULL /* pShared (always null)*/);
1250 if (object->backBuffer != NULL)
1251 IWineD3DSurface_SetContainer(object->backBuffer, (IUnknown *)object);
1253 /* Under directX swapchains share the depth stencil, so only create one depth-stencil */
1254 if (pPresentationParameters->EnableAutoDepthStencil) {
1255 TRACE("Creating depth stencil buffer\n");
1256 if (This->depthStencilBuffer == NULL ) {
1257 hr = D3DCB_CreateDepthStencil((IUnknown *) This->parent,
1258 object->presentParms.BackBufferWidth,
1259 object->presentParms.BackBufferHeight,
1260 object->presentParms.AutoDepthStencilFormat,
1261 object->presentParms.MultiSampleType,
1262 object->presentParms.MultiSampleQuality,
1263 FALSE /* FIXME: Discard */,
1264 &This->depthStencilBuffer,
1265 NULL /* pShared (always null)*/ );
1266 if (This->depthStencilBuffer != NULL)
1267 IWineD3DSurface_SetContainer(This->depthStencilBuffer, (IUnknown *)iface);
1270 /** TODO: A check on width, height and multisample types
1271 *(since the zbuffer must be at least as large as the render target and have the same multisample parameters)
1272 ****************************/
1273 object->wantsDepthStencilBuffer = TRUE;
1275 object->wantsDepthStencilBuffer = FALSE;
1278 TRACE("FrontBuf @ %p, BackBuf @ %p, DepthStencil %d\n",object->frontBuffer, object->backBuffer, object->wantsDepthStencilBuffer);
1281 /*********************
1282 * init the default renderTarget management
1283 *******************/
1284 object->drawable = object->win;
1285 object->render_ctx = object->glCtx;
1288 /*********************
1289 * Setup some defaults and clear down the buffers
1290 *******************/
1292 /** save current context and drawable **/
1293 oldContext = glXGetCurrentContext();
1294 oldDrawable = glXGetCurrentDrawable();
1296 TRACE("Activating context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1297 if (glXMakeCurrent(object->display, object->win, object->glCtx) == False) {
1298 ERR("Error in setting current context (display %p context %p drawable %ld)!\n", object->display, object->glCtx, object->win);
1300 checkGLcall("glXMakeCurrent");
1302 TRACE("Setting up the screen\n");
1303 /* Clear the screen */
1304 glClearColor(0.0, 0.0, 0.0, 0.0);
1305 checkGLcall("glClearColor");
1308 glClearStencil(0xffff);
1310 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1311 checkGLcall("glClear");
1313 glColor3f(1.0, 1.0, 1.0);
1314 checkGLcall("glColor3f");
1316 glEnable(GL_LIGHTING);
1317 checkGLcall("glEnable");
1319 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
1320 checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);");
1322 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1323 checkGLcall("glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);");
1325 glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);
1326 checkGLcall("glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL, GL_SEPARATE_SPECULAR_COLOR);");
1328 /* switch back to the original context (unless it was zero)*/
1329 if (This->swapchains != NULL) {
1330 /** TODO: restore the context and drawable **/
1331 glXMakeCurrent(object->display, oldDrawable, oldContext);
1336 { /* Finally add the swapchain to the end of the devices' swapchain list */
1337 SwapChainList **nextSwapchain;
1338 nextSwapchain = &This->swapchains;
1339 while(*nextSwapchain != NULL) {
1340 nextSwapchain = &((*nextSwapchain)->next);
1342 (*nextSwapchain) = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This->swapchains));
1343 (*nextSwapchain)->swapchain = (IWineD3DSwapChain *)object;
1345 TRACE("Set swapchain to %p\n", object);
1346 } else { /* something went wrong so clean up */
1347 IUnknown* bufferParent;
1348 if (object->frontBuffer) {
1349 IWineD3DSurface_GetParent(object->frontBuffer, &bufferParent);
1350 IUnknown_Release(bufferParent); /* once for the get parent */
1351 if(IUnknown_Release(bufferParent) > 0) {
1352 FIXME("(%p) Something's still holding the front buffer\n",This);
1355 if (object->backBuffer) {
1356 IWineD3DSurface_GetParent(object->backBuffer, &bufferParent);
1357 IUnknown_Release(bufferParent); /* once for the get parent */
1358 if(IUnknown_Release(bufferParent) > 0) {
1359 FIXME("(%p) Something's still holding the back buffer\n",This);
1362 /* NOTE: don't clean up the depthstencil buffer because it belongs to the device */
1363 /* Clean up the context */
1364 /* check that we are the current context first (we shouldn't be though!) */
1365 if (object->glCtx != 0) {
1366 if(glXGetCurrentContext() == object->glCtx) {
1367 glXMakeCurrent(object->display, None, NULL);
1369 glXDestroyContext(object->display, object->glCtx);
1371 HeapFree(GetProcessHeap(), 0, object);
1377 /** NOTE: These are ahead of the other getters and setters to save using a forward declaration **/
1378 UINT WINAPI IWineD3DDeviceImpl_GetNumberOfSwapChains(IWineD3DDevice *iface) {
1379 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1380 unsigned int numberOfSwapChains = 0;
1381 SwapChainList *swapchain;
1383 swapchain = This->swapchains;
1384 /* itterate through the list to get a count */
1385 while (swapchain != NULL) {
1386 swapchain = swapchain->next;
1387 numberOfSwapChains++;
1390 TRACE("(%p) returning %d\n", This, numberOfSwapChains);
1391 return numberOfSwapChains;
1394 HRESULT WINAPI IWineD3DDeviceImpl_GetSwapChain(IWineD3DDevice *iface, UINT iSwapChain, IWineD3DSwapChain **pSwapChain) {
1395 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1396 SwapChainList *swapchain;
1397 HRESULT hr = D3DERR_INVALIDCALL;
1398 swapchain = This->swapchains;
1399 TRACE("(%p) : swapchain %d \n", This, iSwapChain);
1402 TRACE("(%p) Finding swapchain %d\n", This, iSwapChain);
1403 while (iSwapChain > 0 && swapchain != NULL) {
1404 swapchain = swapchain->next;
1408 if (iSwapChain > 0 || swapchain == NULL) {
1409 FIXME("(%p) Unable to find swapchain %d\n", This, iSwapChain);
1412 /** TODO: move off to a linkesList implementation **/
1413 *pSwapChain = swapchain->swapchain;
1414 IWineD3DSwapChain_AddRef(*pSwapChain);
1418 TRACE("(%p) returning %p\n", This, *pSwapChain);
1422 HRESULT WINAPI IWineD3DDeviceImpl_Reset(IWineD3DDevice* iface, WINED3DPRESENT_PARAMETERS* pPresentationParameters) {
1423 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1425 FIXME("(%p) : Stub\n",This);
1431 * Vertex Declaration
1433 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexDeclaration(IWineD3DDevice* iface, CONST VOID* pDeclaration, IWineD3DVertexDeclaration** ppVertexDeclaration, IUnknown *parent) {
1434 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1435 IWineD3DVertexDeclarationImpl *object = NULL;
1436 HRESULT hr = D3D_OK;
1437 TRACE("(%p) : directXVersion=%u, pFunction=%p, ppDecl=%p\n", This, ((IWineD3DImpl *)This->wineD3D)->dxVersion, pDeclaration, ppVertexDeclaration);
1438 D3DCREATEOBJECTINSTANCE(object, VertexDeclaration)
1441 hr = IWineD3DVertexDeclaration_SetDeclaration((IWineD3DVertexDeclaration *)object, (void *)pDeclaration);
1446 /* http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c/directx/graphics/programmingguide/programmable/vertexshaders/vscreate.asp */
1447 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DVertexShader** ppVertexShader, IUnknown *parent) {
1448 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1449 IWineD3DVertexShaderImpl *object; /* NOTE: impl usage is ok, this is a create */
1450 D3DCREATEOBJECTINSTANCE(object, VertexShader)
1451 object->function = pFunction;
1452 FIXME("(%p) : STUB: Created Vertex shader %p\n", This, ppVertexShader);
1457 HRESULT WINAPI IWineD3DDeviceImpl_CreatePixelShader(IWineD3DDevice* iface, CONST DWORD* pFunction, IWineD3DPixelShader** ppPixelShader, IUnknown *parent) {
1458 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1459 FIXME("(%p) : Stub\n", This);
1463 HRESULT WINAPI IWineD3DDeviceImpl_GetDirect3D(IWineD3DDevice* iface, IWineD3D** ppD3D) {
1464 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1465 *ppD3D= This->wineD3D;
1466 TRACE("(%p) : wineD3D returning %p\n", This, *ppD3D);
1467 IWineD3D_AddRef(*ppD3D);
1472 UINT WINAPI IWineD3DDeviceImpl_GetAvailableTextureMem(IWineD3DDevice *iface) {
1473 /** NOTE: There's a probably a hack-around for this one by putting as many pbuffers, VBO's (or whatever)
1474 * Into the video ram as possible and seeing how many fit
1475 * you can also get the correct initial value from via X and ATI's driver
1476 *******************/
1477 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1478 static BOOL showfixmes = TRUE;
1480 FIXME("(%p) : stub, emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1481 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1484 TRACE("(%p) : emulating %dMib for now, returning %dMib\n", This, (emulated_textureram/(1024*1024)),
1485 ((emulated_textureram - wineD3DGlobalStatistics->glsurfaceram) / (1024*1024)));
1486 /* videomemory is simulated videomemory + AGP memory left */
1487 return (emulated_textureram - wineD3DGlobalStatistics->glsurfaceram);
1495 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
1496 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1498 /* Update the current state block */
1499 This->updateStateBlock->fvf = fvf;
1500 This->updateStateBlock->changed.fvf = TRUE;
1501 This->updateStateBlock->set.fvf = TRUE;
1503 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
1504 /* clear down the vertex declaration
1505 NOTE: Axis and Allies doesn't work properly otherwise
1506 (may be a stateblock problem though!)
1508 /* No difference if recording or not */
1509 return IWineD3DDevice_SetVertexDeclaration(iface, NULL);
1514 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
1515 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1516 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
1517 *pfvf = This->stateBlock->fvf;
1522 * Get / Set Stream Source
1524 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
1525 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1526 IWineD3DVertexBuffer *oldSrc;
1528 oldSrc = This->stateBlock->streamSource[StreamNumber];
1529 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
1531 This->updateStateBlock->changed.streamSource[StreamNumber] = TRUE;
1532 This->updateStateBlock->set.streamSource[StreamNumber] = TRUE;
1533 This->updateStateBlock->streamStride[StreamNumber] = Stride;
1534 This->updateStateBlock->streamSource[StreamNumber] = pStreamData;
1535 This->updateStateBlock->streamOffset[StreamNumber] = OffsetInBytes;
1537 /* Handle recording of state blocks */
1538 if (This->isRecordingState) {
1539 TRACE("Recording... not performing anything\n");
1543 /* Not recording... */
1544 if (pStreamData != NULL) {
1545 IUnknown *newVertexBufferParent;
1546 /* GetParent will add a ref, so leave it hanging until the vertex buffer is cleared */
1547 IWineD3DVertexBuffer_GetParent(pStreamData, &newVertexBufferParent);
1549 if (oldSrc != NULL) {
1550 IUnknown *oldVertexBufferParent;
1551 IWineD3DVertexBuffer_GetParent(oldSrc, &oldVertexBufferParent);
1552 IUnknown_Release(oldVertexBufferParent);
1553 IUnknown_Release(oldVertexBufferParent);
1559 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
1560 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1562 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->streamSource[StreamNumber], This->stateBlock->streamStride[StreamNumber]);
1563 *pStream = This->stateBlock->streamSource[StreamNumber];
1564 *pStride = This->stateBlock->streamStride[StreamNumber];
1565 *pOffset = This->stateBlock->streamOffset[StreamNumber];
1566 if (*pStream != NULL) IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
1570 /*Should be quite easy, just an extension of vertexdata
1572 http://msdn.microsoft.com/archive/default.asp?url=/archive/en-us/directx9_c_Summer_04/directx/graphics/programmingguide/advancedtopics/DrawingMultipleInstances.asp
1574 The divider is a bit odd though
1576 VertexOffset = StartVertex / Divider * StreamStride +
1577 VertexIndex / Divider * StreamStride + StreamOffset
1580 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT Divider) {
1581 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1583 FIXME("(%p) : stub\n", This);
1587 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSourceFreq(IWineD3DDevice *iface, UINT StreamNumber, UINT* Divider) {
1588 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1590 FIXME("(%p) : stub\n", This);
1595 * Get / Set & Multiply Transform
1597 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1598 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1600 /* Most of this routine, comments included copied from ddraw tree initially: */
1601 TRACE("(%p) : Transform State=%d\n", This, d3dts);
1603 /* Handle recording of state blocks */
1604 if (This->isRecordingState) {
1605 TRACE("Recording... not performing anything\n");
1606 This->updateStateBlock->changed.transform[d3dts] = TRUE;
1607 This->updateStateBlock->set.transform[d3dts] = TRUE;
1608 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1613 * If the new matrix is the same as the current one,
1614 * we cut off any further processing. this seems to be a reasonable
1615 * optimization because as was noticed, some apps (warcraft3 for example)
1616 * tend towards setting the same matrix repeatedly for some reason.
1618 * From here on we assume that the new matrix is different, wherever it matters.
1620 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1621 TRACE("The app is setting the same matrix over again\n");
1624 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
1628 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1629 where ViewMat = Camera space, WorldMat = world space.
1631 In OpenGL, camera and world space is combined into GL_MODELVIEW
1632 matrix. The Projection matrix stay projection matrix.
1635 /* Capture the times we can just ignore the change for now */
1636 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1637 This->modelview_valid = FALSE;
1640 } else if (d3dts == D3DTS_PROJECTION) {
1641 This->proj_valid = FALSE;
1644 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
1645 /* Indexed Vertex Blending Matrices 256 -> 511 */
1646 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1647 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1651 /* Now we really are going to have to change a matrix */
1654 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1655 if (d3dts < GL_LIMITS(textures)) {
1656 int tex = d3dts - D3DTS_TEXTURE0;
1657 GLACTIVETEXTURE(tex);
1658 set_texture_matrix((float *)lpmatrix,
1659 This->updateStateBlock->textureState[tex][WINED3DTSS_TEXTURETRANSFORMFLAGS], (This->stateBlock->textureState[tex][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU);
1662 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1665 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1666 * NOTE: We have to reset the positions even if the light/plane is not currently
1667 * enabled, since the call to enable it will not reset the position.
1668 * NOTE2: Apparently texture transforms do NOT need reapplying
1671 PLIGHTINFOEL *lightChain = NULL;
1672 This->modelview_valid = FALSE;
1673 This->view_ident = !memcmp(lpmatrix, identity, 16 * sizeof(float));
1675 glMatrixMode(GL_MODELVIEW);
1676 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1678 glLoadMatrixf((float *)lpmatrix);
1679 checkGLcall("glLoadMatrixf(...)");
1682 lightChain = This->stateBlock->lights;
1683 while (lightChain && lightChain->glIndex != -1) {
1684 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1685 checkGLcall("glLightfv posn");
1686 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1687 checkGLcall("glLightfv dirn");
1688 lightChain = lightChain->next;
1691 /* Reset Clipping Planes if clipping is enabled */
1692 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1693 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
1694 checkGLcall("glClipPlane");
1698 } else { /* What was requested!?? */
1699 WARN("invalid matrix specified: %i\n", d3dts);
1702 /* Release lock, all done */
1707 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
1708 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1709 TRACE("(%p) : for Transform State %d\n", This, State);
1710 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
1714 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1715 D3DMATRIX *mat = NULL;
1718 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
1719 * below means it will be recorded in a state block change, but it
1720 * works regardless where it is recorded.
1721 * If this is found to be wrong, change to StateBlock.
1723 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1724 TRACE("(%p) : For state %u\n", This, State);
1726 if (State < HIGHEST_TRANSFORMSTATE)
1728 mat = &This->updateStateBlock->transforms[State];
1730 FIXME("Unhandled transform state!!\n");
1733 /* Copied from ddraw code: */
1734 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);
1735 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);
1736 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);
1737 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);
1739 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);
1740 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);
1741 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);
1742 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);
1744 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);
1745 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);
1746 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);
1747 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);
1749 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);
1750 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);
1751 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);
1752 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);
1754 /* Apply change via set transform - will reapply to eg. lights this way */
1755 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
1761 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
1763 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1764 you can reference any indexes you want as long as that number max are enabled at any
1765 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1766 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1767 but when recording, just build a chain pretty much of commands to be replayed. */
1769 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
1771 PLIGHTINFOEL *object, *temp;
1773 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1774 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1776 /* If recording state block, just add to end of lights chain */
1777 if (This->isRecordingState) {
1778 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1779 if (NULL == object) {
1780 return D3DERR_OUTOFVIDEOMEMORY;
1782 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1783 object->OriginalIndex = Index;
1784 object->glIndex = -1;
1785 object->changed = TRUE;
1787 /* Add to the END of the chain of lights changes to be replayed */
1788 if (This->updateStateBlock->lights == NULL) {
1789 This->updateStateBlock->lights = object;
1791 temp = This->updateStateBlock->lights;
1792 while (temp->next != NULL) temp=temp->next;
1793 temp->next = object;
1795 TRACE("Recording... not performing anything more\n");
1799 /* Ok, not recording any longer so do real work */
1800 object = This->stateBlock->lights;
1801 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1803 /* If we didn't find it in the list of lights, time to add it */
1804 if (object == NULL) {
1805 PLIGHTINFOEL *insertAt,*prevPos;
1807 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1808 if (NULL == object) {
1809 return D3DERR_OUTOFVIDEOMEMORY;
1811 object->OriginalIndex = Index;
1812 object->glIndex = -1;
1814 /* Add it to the front of list with the idea that lights will be changed as needed
1815 BUT after any lights currently assigned GL indexes */
1816 insertAt = This->stateBlock->lights;
1818 while (insertAt != NULL && insertAt->glIndex != -1) {
1820 insertAt = insertAt->next;
1823 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1824 This->stateBlock->lights = object;
1825 } else if (insertAt == NULL) { /* End of list */
1826 prevPos->next = object;
1827 object->prev = prevPos;
1828 } else { /* Middle of chain */
1829 if (prevPos == NULL) {
1830 This->stateBlock->lights = object;
1832 prevPos->next = object;
1834 object->prev = prevPos;
1835 object->next = insertAt;
1836 insertAt->prev = object;
1840 /* Initialze the object */
1841 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,
1842 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1843 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1844 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1845 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1846 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1847 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1849 /* Save away the information */
1850 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1852 switch (pLight->Type) {
1853 case D3DLIGHT_POINT:
1855 object->lightPosn[0] = pLight->Position.x;
1856 object->lightPosn[1] = pLight->Position.y;
1857 object->lightPosn[2] = pLight->Position.z;
1858 object->lightPosn[3] = 1.0f;
1859 object->cutoff = 180.0f;
1863 case D3DLIGHT_DIRECTIONAL:
1865 object->lightPosn[0] = -pLight->Direction.x;
1866 object->lightPosn[1] = -pLight->Direction.y;
1867 object->lightPosn[2] = -pLight->Direction.z;
1868 object->lightPosn[3] = 0.0;
1869 object->exponent = 0.0f;
1870 object->cutoff = 180.0f;
1875 object->lightPosn[0] = pLight->Position.x;
1876 object->lightPosn[1] = pLight->Position.y;
1877 object->lightPosn[2] = pLight->Position.z;
1878 object->lightPosn[3] = 1.0;
1881 object->lightDirn[0] = pLight->Direction.x;
1882 object->lightDirn[1] = pLight->Direction.y;
1883 object->lightDirn[2] = pLight->Direction.z;
1884 object->lightDirn[3] = 1.0;
1887 * opengl-ish and d3d-ish spot lights use too different models for the
1888 * light "intensity" as a function of the angle towards the main light direction,
1889 * so we only can approximate very roughly.
1890 * however spot lights are rather rarely used in games (if ever used at all).
1891 * furthermore if still used, probably nobody pays attention to such details.
1893 if (pLight->Falloff == 0) {
1896 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1898 if (rho < 0.0001) rho = 0.0001f;
1899 object->exponent = -0.3/log(cos(rho/2));
1900 object->cutoff = pLight->Phi*90/M_PI;
1906 FIXME("Unrecognized light type %d\n", pLight->Type);
1909 /* Update the live definitions if the light is currently assigned a glIndex */
1910 if (object->glIndex != -1) {
1911 setup_light(iface, object->glIndex, object);
1916 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1917 PLIGHTINFOEL *lightInfo = NULL;
1918 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1919 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1921 /* Locate the light in the live lights */
1922 lightInfo = This->stateBlock->lights;
1923 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1925 if (lightInfo == NULL) {
1926 TRACE("Light information requested but light not defined\n");
1927 return D3DERR_INVALIDCALL;
1930 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1935 * Get / Set Light Enable
1936 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1938 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1939 PLIGHTINFOEL *lightInfo = NULL;
1940 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1941 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1943 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1944 if (This->isRecordingState) {
1945 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1946 if (NULL == lightInfo) {
1947 return D3DERR_OUTOFVIDEOMEMORY;
1949 lightInfo->OriginalIndex = Index;
1950 lightInfo->glIndex = -1;
1951 lightInfo->enabledChanged = TRUE;
1953 /* Add to the END of the chain of lights changes to be replayed */
1954 if (This->updateStateBlock->lights == NULL) {
1955 This->updateStateBlock->lights = lightInfo;
1957 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1958 while (temp->next != NULL) temp=temp->next;
1959 temp->next = lightInfo;
1961 TRACE("Recording... not performing anything more\n");
1965 /* Not recording... So, locate the light in the live lights */
1966 lightInfo = This->stateBlock->lights;
1967 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1969 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1970 if (lightInfo == NULL) {
1971 D3DLIGHT9 lightParms;
1972 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1973 wait until someone confirms it seems to work! */
1974 TRACE("Light enabled requested but light not defined, so defining one!\n");
1975 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1976 lightParms.Diffuse.r = 1.0;
1977 lightParms.Diffuse.g = 1.0;
1978 lightParms.Diffuse.b = 1.0;
1979 lightParms.Diffuse.a = 0.0;
1980 lightParms.Specular.r = 0.0;
1981 lightParms.Specular.g = 0.0;
1982 lightParms.Specular.b = 0.0;
1983 lightParms.Specular.a = 0.0;
1984 lightParms.Ambient.r = 0.0;
1985 lightParms.Ambient.g = 0.0;
1986 lightParms.Ambient.b = 0.0;
1987 lightParms.Ambient.a = 0.0;
1988 lightParms.Position.x = 0.0;
1989 lightParms.Position.y = 0.0;
1990 lightParms.Position.z = 0.0;
1991 lightParms.Direction.x = 0.0;
1992 lightParms.Direction.y = 0.0;
1993 lightParms.Direction.z = 1.0;
1994 lightParms.Range = 0.0;
1995 lightParms.Falloff = 0.0;
1996 lightParms.Attenuation0 = 0.0;
1997 lightParms.Attenuation1 = 0.0;
1998 lightParms.Attenuation2 = 0.0;
1999 lightParms.Theta = 0.0;
2000 lightParms.Phi = 0.0;
2001 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
2003 /* Search for it again! Should be fairly quick as near head of list */
2004 lightInfo = This->stateBlock->lights;
2005 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2006 if (lightInfo == NULL) {
2007 FIXME("Adding default lights has failed dismally\n");
2008 return D3DERR_INVALIDCALL;
2012 /* OK, we now have a light... */
2013 if (Enable == FALSE) {
2015 /* If we are disabling it, check it was enabled, and
2016 still only do something if it has assigned a glIndex (which it should have!) */
2017 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
2018 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
2020 glDisable(GL_LIGHT0 + lightInfo->glIndex);
2021 checkGLcall("glDisable GL_LIGHT0+Index");
2024 TRACE("Nothing to do as light was not enabled\n");
2026 lightInfo->lightEnabled = FALSE;
2029 /* We are enabling it. If it is enabled, it's really simple */
2030 if (lightInfo->lightEnabled) {
2032 TRACE("Nothing to do as light was enabled\n");
2034 /* If it already has a glIndex, it's still simple */
2035 } else if (lightInfo->glIndex != -1) {
2036 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
2037 lightInfo->lightEnabled = TRUE;
2039 glEnable(GL_LIGHT0 + lightInfo->glIndex);
2040 checkGLcall("glEnable GL_LIGHT0+Index already setup");
2043 /* Otherwise got to find space - lights are ordered gl indexes first */
2045 PLIGHTINFOEL *bsf = NULL;
2046 PLIGHTINFOEL *pos = This->stateBlock->lights;
2047 PLIGHTINFOEL *prev = NULL;
2051 /* Try to minimize changes as much as possible */
2052 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2054 /* Try to remember which index can be replaced if necessary */
2055 if (bsf==NULL && pos->lightEnabled == FALSE) {
2056 /* Found a light we can replace, save as best replacement */
2060 /* Step to next space */
2066 /* If we have too many active lights, fail the call */
2067 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2068 FIXME("Program requests too many concurrent lights\n");
2069 return D3DERR_INVALIDCALL;
2071 /* If we have allocated all lights, but not all are enabled,
2072 reuse one which is not enabled */
2073 } else if (Index == This->maxConcurrentLights) {
2074 /* use bsf - Simply swap the new light and the BSF one */
2075 PLIGHTINFOEL *bsfNext = bsf->next;
2076 PLIGHTINFOEL *bsfPrev = bsf->prev;
2079 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2080 if (bsf->prev != NULL) {
2081 bsf->prev->next = lightInfo;
2083 This->stateBlock->lights = lightInfo;
2086 /* If not side by side, lots of chains to update */
2087 if (bsf->next != lightInfo) {
2088 lightInfo->prev->next = bsf;
2089 bsf->next->prev = lightInfo;
2090 bsf->next = lightInfo->next;
2091 bsf->prev = lightInfo->prev;
2092 lightInfo->next = bsfNext;
2093 lightInfo->prev = bsfPrev;
2097 bsf->prev = lightInfo;
2098 bsf->next = lightInfo->next;
2099 lightInfo->next = bsf;
2100 lightInfo->prev = bsfPrev;
2105 glIndex = bsf->glIndex;
2107 lightInfo->glIndex = glIndex;
2108 lightInfo->lightEnabled = TRUE;
2110 /* Finally set up the light in gl itself */
2111 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2113 setup_light(iface, glIndex, lightInfo);
2114 glEnable(GL_LIGHT0 + glIndex);
2115 checkGLcall("glEnable GL_LIGHT0 new setup");
2118 /* If we reached the end of the allocated lights, with space in the
2119 gl lights, setup a new light */
2120 } else if (pos->glIndex == -1) {
2122 /* We reached the end of the allocated gl lights, so already
2123 know the index of the next one! */
2125 lightInfo->glIndex = glIndex;
2126 lightInfo->lightEnabled = TRUE;
2128 /* In an ideal world, it's already in the right place */
2129 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2130 /* No need to move it */
2132 /* Remove this light from the list */
2133 lightInfo->prev->next = lightInfo->next;
2134 if (lightInfo->next != NULL) {
2135 lightInfo->next->prev = lightInfo->prev;
2138 /* Add in at appropriate place (inbetween prev and pos) */
2139 lightInfo->prev = prev;
2140 lightInfo->next = pos;
2142 This->stateBlock->lights = lightInfo;
2144 prev->next = lightInfo;
2147 pos->prev = lightInfo;
2151 /* Finally set up the light in gl itself */
2152 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2154 setup_light(iface, glIndex, lightInfo);
2155 glEnable(GL_LIGHT0 + glIndex);
2156 checkGLcall("glEnable GL_LIGHT0 new setup");
2165 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
2167 PLIGHTINFOEL *lightInfo = NULL;
2168 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2169 TRACE("(%p) : for idx(%ld)\n", This, Index);
2171 /* Locate the light in the live lights */
2172 lightInfo = This->stateBlock->lights;
2173 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2175 if (lightInfo == NULL) {
2176 TRACE("Light enabled state requested but light not defined\n");
2177 return D3DERR_INVALIDCALL;
2179 *pEnable = lightInfo->lightEnabled;
2184 * Get / Set Clip Planes
2186 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
2187 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2188 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2190 /* Validate Index */
2191 if (Index >= GL_LIMITS(clipplanes)) {
2192 TRACE("Application has requested clipplane this device doesn't support\n");
2193 return D3DERR_INVALIDCALL;
2196 This->updateStateBlock->changed.clipplane[Index] = TRUE;
2197 This->updateStateBlock->set.clipplane[Index] = TRUE;
2198 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
2199 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
2200 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
2201 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
2203 /* Handle recording of state blocks */
2204 if (This->isRecordingState) {
2205 TRACE("Recording... not performing anything\n");
2213 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2214 glMatrixMode(GL_MODELVIEW);
2216 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2218 TRACE("Clipplane [%f,%f,%f,%f]\n",
2219 This->updateStateBlock->clipplane[Index][0],
2220 This->updateStateBlock->clipplane[Index][1],
2221 This->updateStateBlock->clipplane[Index][2],
2222 This->updateStateBlock->clipplane[Index][3]);
2223 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
2224 checkGLcall("glClipPlane");
2232 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
2233 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2234 TRACE("(%p) : for idx %ld\n", This, Index);
2236 /* Validate Index */
2237 if (Index >= GL_LIMITS(clipplanes)) {
2238 TRACE("Application has requested clipplane this device doesn't support\n");
2239 return D3DERR_INVALIDCALL;
2242 pPlane[0] = This->stateBlock->clipplane[Index][0];
2243 pPlane[1] = This->stateBlock->clipplane[Index][1];
2244 pPlane[2] = This->stateBlock->clipplane[Index][2];
2245 pPlane[3] = This->stateBlock->clipplane[Index][3];
2250 * Get / Set Clip Plane Status
2251 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
2253 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
2254 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2255 FIXME("(%p) : stub\n", This);
2256 if (NULL == pClipStatus) {
2257 return D3DERR_INVALIDCALL;
2259 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2260 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2264 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
2265 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2266 FIXME("(%p) : stub\n", This);
2267 if (NULL == pClipStatus) {
2268 return D3DERR_INVALIDCALL;
2270 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
2271 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
2276 * Get / Set Material
2277 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
2279 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
2280 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2282 This->updateStateBlock->changed.material = TRUE;
2283 This->updateStateBlock->set.material = TRUE;
2284 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
2286 /* Handle recording of state blocks */
2287 if (This->isRecordingState) {
2288 TRACE("Recording... not performing anything\n");
2293 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2294 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2295 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2296 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2297 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2299 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
2300 checkGLcall("glMaterialfv");
2301 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
2302 checkGLcall("glMaterialfv");
2304 /* Only change material color if specular is enabled, otherwise it is set to black */
2305 if (This->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
2306 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2307 checkGLcall("glMaterialfv");
2309 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2310 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2311 checkGLcall("glMaterialfv");
2313 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
2314 checkGLcall("glMaterialfv");
2315 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
2316 checkGLcall("glMaterialf");
2322 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
2323 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2324 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
2325 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
2326 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
2327 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
2328 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
2329 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
2336 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
2337 UINT BaseVertexIndex) {
2338 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2339 IWineD3DIndexBuffer *oldIdxs;
2341 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
2342 oldIdxs = This->updateStateBlock->pIndexData;
2344 This->updateStateBlock->changed.indices = TRUE;
2345 This->updateStateBlock->set.indices = TRUE;
2346 This->updateStateBlock->pIndexData = pIndexData;
2347 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
2349 /* Handle recording of state blocks */
2350 if (This->isRecordingState) {
2351 TRACE("Recording... not performing anything\n");
2356 IUnknown *indexBufferParent;
2357 /* Getting the parent causes a addRef... it gets released when the indicies are clear */
2358 IWineD3DIndexBuffer_GetParent(pIndexData, &indexBufferParent);
2361 IUnknown *indexBufferParent;
2362 IWineD3DIndexBuffer_GetParent(oldIdxs, &indexBufferParent);
2363 IUnknown_Release(indexBufferParent);
2364 IUnknown_Release(indexBufferParent);
2369 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
2370 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2372 *ppIndexData = This->stateBlock->pIndexData;
2374 /* up ref count on ppindexdata */
2375 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
2376 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
2382 * Get / Set Viewports
2384 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
2385 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2387 TRACE("(%p)\n", This);
2388 This->updateStateBlock->changed.viewport = TRUE;
2389 This->updateStateBlock->set.viewport = TRUE;
2390 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
2392 /* Handle recording of state blocks */
2393 if (This->isRecordingState) {
2394 TRACE("Recording... not performing anything\n");
2400 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
2401 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
2403 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
2404 checkGLcall("glDepthRange");
2405 /* Note: GL requires lower left, DirectX supplies upper left */
2406 /* TODO: replace usage of renderTarget with context management */
2407 glViewport(pViewport->X,
2408 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
2409 pViewport->Width, pViewport->Height);
2411 checkGLcall("glViewport");
2419 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
2420 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2421 TRACE("(%p)\n", This);
2422 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
2427 * Get / Set Render States
2428 * TODO: Verify against dx9 definitions
2430 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
2432 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2433 DWORD OldValue = This->stateBlock->renderState[State];
2435 /* Simple way of referring to either a DWORD or a 4 byte float */
2441 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2442 This->updateStateBlock->changed.renderState[State] = TRUE;
2443 This->updateStateBlock->set.renderState[State] = TRUE;
2444 This->updateStateBlock->renderState[State] = Value;
2446 /* Handle recording of state blocks */
2447 if (This->isRecordingState) {
2448 TRACE("Recording... not performing anything\n");
2455 case WINED3DRS_FILLMODE :
2456 switch ((D3DFILLMODE) Value) {
2457 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2458 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2459 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2461 FIXME("Unrecognized WINED3DRS_FILLMODE value %ld\n", Value);
2463 checkGLcall("glPolygonMode (fillmode)");
2466 case WINED3DRS_LIGHTING :
2468 glEnable(GL_LIGHTING);
2469 checkGLcall("glEnable GL_LIGHTING");
2471 glDisable(GL_LIGHTING);
2472 checkGLcall("glDisable GL_LIGHTING");
2476 case WINED3DRS_ZENABLE :
2477 switch ((D3DZBUFFERTYPE) Value) {
2479 glDisable(GL_DEPTH_TEST);
2480 checkGLcall("glDisable GL_DEPTH_TEST");
2483 glEnable(GL_DEPTH_TEST);
2484 checkGLcall("glEnable GL_DEPTH_TEST");
2487 glEnable(GL_DEPTH_TEST);
2488 checkGLcall("glEnable GL_DEPTH_TEST");
2489 FIXME("W buffer is not well handled\n");
2492 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2496 case WINED3DRS_CULLMODE :
2498 /* If we are culling "back faces with clockwise vertices" then
2499 set front faces to be counter clockwise and enable culling
2501 switch ((D3DCULL) Value) {
2503 glDisable(GL_CULL_FACE);
2504 checkGLcall("glDisable GL_CULL_FACE");
2507 glEnable(GL_CULL_FACE);
2508 checkGLcall("glEnable GL_CULL_FACE");
2509 if (This->renderUpsideDown) {
2511 checkGLcall("glFrontFace GL_CW");
2513 glFrontFace(GL_CCW);
2514 checkGLcall("glFrontFace GL_CCW");
2516 glCullFace(GL_BACK);
2519 glEnable(GL_CULL_FACE);
2520 checkGLcall("glEnable GL_CULL_FACE");
2521 if (This->renderUpsideDown) {
2522 glFrontFace(GL_CCW);
2523 checkGLcall("glFrontFace GL_CCW");
2526 checkGLcall("glFrontFace GL_CW");
2528 glCullFace(GL_BACK);
2531 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2535 case WINED3DRS_SHADEMODE :
2536 switch ((D3DSHADEMODE) Value) {
2538 glShadeModel(GL_FLAT);
2539 checkGLcall("glShadeModel");
2541 case D3DSHADE_GOURAUD:
2542 glShadeModel(GL_SMOOTH);
2543 checkGLcall("glShadeModel");
2545 case D3DSHADE_PHONG:
2546 FIXME("D3DSHADE_PHONG isn't supported?\n");
2549 return D3DERR_INVALIDCALL;
2551 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2555 case WINED3DRS_DITHERENABLE :
2557 glEnable(GL_DITHER);
2558 checkGLcall("glEnable GL_DITHER");
2560 glDisable(GL_DITHER);
2561 checkGLcall("glDisable GL_DITHER");
2565 case WINED3DRS_ZWRITEENABLE :
2568 checkGLcall("glDepthMask");
2571 checkGLcall("glDepthMask");
2575 case WINED3DRS_ZFUNC :
2577 int glParm = GL_LESS;
2579 switch ((D3DCMPFUNC) Value) {
2580 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2581 case D3DCMP_LESS: glParm=GL_LESS; break;
2582 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2583 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2584 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2585 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2586 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2587 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2589 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2591 glDepthFunc(glParm);
2592 checkGLcall("glDepthFunc");
2596 case WINED3DRS_AMBIENT :
2599 D3DCOLORTOGLFLOAT4(Value, col);
2600 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2601 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2602 checkGLcall("glLightModel for MODEL_AMBIENT");
2607 case WINED3DRS_ALPHABLENDENABLE :
2610 checkGLcall("glEnable GL_BLEND");
2612 glDisable(GL_BLEND);
2613 checkGLcall("glDisable GL_BLEND");
2617 case WINED3DRS_SRCBLEND :
2618 case WINED3DRS_DESTBLEND :
2620 int newVal = GL_ZERO;
2622 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2623 case D3DBLEND_ONE : newVal = GL_ONE; break;
2624 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2625 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2626 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2627 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2628 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2629 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2630 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2631 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2632 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2634 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2635 This->srcBlend = newVal;
2636 This->dstBlend = newVal;
2639 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2640 This->srcBlend = newVal;
2641 This->dstBlend = newVal;
2644 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2647 if (State == WINED3DRS_SRCBLEND) This->srcBlend = newVal;
2648 if (State == WINED3DRS_DESTBLEND) This->dstBlend = newVal;
2649 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2650 glBlendFunc(This->srcBlend, This->dstBlend);
2652 checkGLcall("glBlendFunc");
2656 case WINED3DRS_ALPHATESTENABLE :
2658 glEnable(GL_ALPHA_TEST);
2659 checkGLcall("glEnable GL_ALPHA_TEST");
2661 glDisable(GL_ALPHA_TEST);
2662 checkGLcall("glDisable GL_ALPHA_TEST");
2666 case WINED3DRS_ALPHAFUNC :
2668 int glParm = GL_LESS;
2669 float ref = ((float) This->stateBlock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
2671 switch ((D3DCMPFUNC) Value) {
2672 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2673 case D3DCMP_LESS: glParm = GL_LESS; break;
2674 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2675 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2676 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2677 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2678 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2679 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2681 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2683 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2684 glAlphaFunc(glParm, ref);
2685 This->alphafunc = glParm;
2686 checkGLcall("glAlphaFunc");
2690 case WINED3DRS_ALPHAREF :
2692 int glParm = This->alphafunc;
2695 ref = ((float) Value) / 255.0f;
2696 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2697 glAlphaFunc(glParm, ref);
2698 checkGLcall("glAlphaFunc");
2702 case WINED3DRS_CLIPPLANEENABLE :
2703 case WINED3DRS_CLIPPING :
2705 /* Ensure we only do the changed clip planes */
2706 DWORD enable = 0xFFFFFFFF;
2707 DWORD disable = 0x00000000;
2709 /* If enabling / disabling all */
2710 if (State == WINED3DRS_CLIPPING) {
2712 enable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2715 disable = This->stateBlock->renderState[WINED3DRS_CLIPPLANEENABLE];
2719 enable = Value & ~OldValue;
2720 disable = ~Value & OldValue;
2723 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2724 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2725 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2726 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2727 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2728 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2730 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2731 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2732 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2733 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2734 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2735 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2737 /** update clipping status */
2739 This->stateBlock->clip_status.ClipUnion = 0;
2740 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2742 This->stateBlock->clip_status.ClipUnion = 0;
2743 This->stateBlock->clip_status.ClipIntersection = 0;
2748 case WINED3DRS_BLENDOP :
2750 int glParm = GL_FUNC_ADD;
2752 switch ((D3DBLENDOP) Value) {
2753 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2754 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2755 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2756 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2757 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2759 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2761 TRACE("glBlendEquation(%x)\n", glParm);
2762 glBlendEquation(glParm);
2763 checkGLcall("glBlendEquation");
2767 case WINED3DRS_TEXTUREFACTOR :
2771 /* Note the texture color applies to all textures whereas
2772 GL_TEXTURE_ENV_COLOR applies to active only */
2774 D3DCOLORTOGLFLOAT4(Value, col);
2775 /* Set the default alpha blend color */
2776 glBlendColor(col[0], col[1], col[2], col[3]);
2777 checkGLcall("glBlendColor");
2779 /* And now the default texture color as well */
2780 for (i = 0; i < GL_LIMITS(textures); i++) {
2782 /* Note the D3DRS value applies to all textures, but GL has one
2783 per texture, so apply it now ready to be used! */
2784 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2787 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2790 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2791 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2796 case WINED3DRS_SPECULARENABLE :
2798 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2799 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2800 specular color. This is wrong:
2801 Separate specular color means the specular colour is maintained separately, whereas
2802 single color means it is merged in. However in both cases they are being used to
2804 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2805 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2809 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
2810 checkGLcall("glMaterialfv");
2811 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2812 glEnable(GL_COLOR_SUM_EXT);
2814 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2816 checkGLcall("glEnable(GL_COLOR_SUM)");
2818 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2820 /* for the case of enabled lighting: */
2821 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2822 checkGLcall("glMaterialfv");
2824 /* for the case of disabled lighting: */
2825 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2826 glDisable(GL_COLOR_SUM_EXT);
2828 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2830 checkGLcall("glDisable(GL_COLOR_SUM)");
2835 case WINED3DRS_STENCILENABLE :
2837 glEnable(GL_STENCIL_TEST);
2838 checkGLcall("glEnable GL_STENCIL_TEST");
2840 glDisable(GL_STENCIL_TEST);
2841 checkGLcall("glDisable GL_STENCIL_TEST");
2845 case WINED3DRS_STENCILFUNC :
2847 int glParm = GL_ALWAYS;
2848 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2849 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2851 switch ((D3DCMPFUNC) Value) {
2852 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2853 case D3DCMP_LESS: glParm=GL_LESS; break;
2854 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2855 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2856 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2857 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2858 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2859 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2861 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2863 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2864 This->stencilfunc = glParm;
2865 glStencilFunc(glParm, ref, mask);
2866 checkGLcall("glStencilFunc");
2870 case WINED3DRS_STENCILREF :
2872 int glParm = This->stencilfunc;
2874 GLuint mask = This->stateBlock->renderState[WINED3DRS_STENCILMASK];
2877 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2878 glStencilFunc(glParm, ref, mask);
2879 checkGLcall("glStencilFunc");
2883 case WINED3DRS_STENCILMASK :
2885 int glParm = This->stencilfunc;
2886 int ref = This->stateBlock->renderState[WINED3DRS_STENCILREF];
2887 GLuint mask = Value;
2889 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2890 glStencilFunc(glParm, ref, mask);
2891 checkGLcall("glStencilFunc");
2895 case WINED3DRS_STENCILFAIL :
2901 fail = StencilOp(Value);
2902 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2903 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2904 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2905 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2907 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2908 glStencilOp(fail, zfail, zpass);
2909 checkGLcall("glStencilOp(fail, zfail, zpass);");
2912 case WINED3DRS_STENCILZFAIL :
2918 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2919 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2920 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2921 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2922 zfail = StencilOp(Value);
2924 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2925 glStencilOp(fail, zfail, zpass);
2926 checkGLcall("glStencilOp(fail, zfail, zpass);");
2929 case WINED3DRS_STENCILPASS :
2935 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2936 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2937 zpass = StencilOp(Value);
2938 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2939 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2941 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2942 glStencilOp(fail, zfail, zpass);
2943 checkGLcall("glStencilOp(fail, zfail, zpass);");
2947 case WINED3DRS_STENCILWRITEMASK :
2949 glStencilMask(Value);
2950 TRACE("glStencilMask(%lu)\n", Value);
2951 checkGLcall("glStencilMask");
2955 case WINED3DRS_FOGENABLE :
2957 if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2959 checkGLcall("glEnable GL_FOG");
2962 checkGLcall("glDisable GL_FOG");
2967 case WINED3DRS_RANGEFOGENABLE :
2970 TRACE("Enabled RANGEFOG");
2972 TRACE("Disabled RANGEFOG");
2977 case WINED3DRS_FOGCOLOR :
2980 D3DCOLORTOGLFLOAT4(Value, col);
2981 /* Set the default alpha blend color */
2982 glFogfv(GL_FOG_COLOR, &col[0]);
2983 checkGLcall("glFog GL_FOG_COLOR");
2987 case WINED3DRS_FOGTABLEMODE :
2989 glHint(GL_FOG_HINT, GL_NICEST);
2991 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2992 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2993 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2994 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2996 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
2998 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2999 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
3004 case WINED3DRS_FOGVERTEXMODE :
3006 glHint(GL_FOG_HINT, GL_FASTEST);
3008 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3009 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
3010 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
3011 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
3013 FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
3015 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
3016 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
3021 case WINED3DRS_FOGSTART :
3024 glFogfv(GL_FOG_START, &tmpvalue.f);
3025 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
3026 TRACE("Fog Start == %f\n", tmpvalue.f);
3030 case WINED3DRS_FOGEND :
3033 glFogfv(GL_FOG_END, &tmpvalue.f);
3034 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
3035 TRACE("Fog End == %f\n", tmpvalue.f);
3039 case WINED3DRS_FOGDENSITY :
3042 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
3043 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
3047 case WINED3DRS_VERTEXBLEND :
3049 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
3050 TRACE("Vertex Blending state to %ld\n", Value);
3054 case WINED3DRS_TWEENFACTOR :
3057 This->updateStateBlock->tween_factor = tmpvalue.f;
3058 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
3062 case WINED3DRS_INDEXEDVERTEXBLENDENABLE :
3064 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
3068 case WINED3DRS_COLORVERTEX :
3069 case WINED3DRS_DIFFUSEMATERIALSOURCE :
3070 case WINED3DRS_SPECULARMATERIALSOURCE :
3071 case WINED3DRS_AMBIENTMATERIALSOURCE :
3072 case WINED3DRS_EMISSIVEMATERIALSOURCE :
3074 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
3076 if (This->stateBlock->renderState[WINED3DRS_COLORVERTEX]) {
3077 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
3078 This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
3079 This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
3080 This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
3081 This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
3083 if (This->stateBlock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
3084 if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3085 Parm = GL_AMBIENT_AND_DIFFUSE;
3089 } else if (This->stateBlock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
3091 } else if (This->stateBlock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
3093 } else if (This->stateBlock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
3100 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3102 This->tracking_color = NEEDS_TRACKING;
3103 This->tracking_parm = Parm;
3107 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
3112 case WINED3DRS_LINEPATTERN :
3118 tmppattern.d = Value;
3120 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3122 if (tmppattern.lp.wRepeatFactor) {
3123 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
3124 checkGLcall("glLineStipple(repeat, linepattern)");
3125 glEnable(GL_LINE_STIPPLE);
3126 checkGLcall("glEnable(GL_LINE_STIPPLE);");
3128 glDisable(GL_LINE_STIPPLE);
3129 checkGLcall("glDisable(GL_LINE_STIPPLE);");
3134 case WINED3DRS_ZBIAS :
3138 TRACE("ZBias value %f\n", tmpvalue.f);
3139 glPolygonOffset(0, -tmpvalue.f);
3140 checkGLcall("glPolygonOffset(0, -Value)");
3141 glEnable(GL_POLYGON_OFFSET_FILL);
3142 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
3143 glEnable(GL_POLYGON_OFFSET_LINE);
3144 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
3145 glEnable(GL_POLYGON_OFFSET_POINT);
3146 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
3148 glDisable(GL_POLYGON_OFFSET_FILL);
3149 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
3150 glDisable(GL_POLYGON_OFFSET_LINE);
3151 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
3152 glDisable(GL_POLYGON_OFFSET_POINT);
3153 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
3158 case WINED3DRS_NORMALIZENORMALS :
3160 glEnable(GL_NORMALIZE);
3161 checkGLcall("glEnable(GL_NORMALIZE);");
3163 glDisable(GL_NORMALIZE);
3164 checkGLcall("glDisable(GL_NORMALIZE);");
3168 case WINED3DRS_POINTSIZE :
3170 TRACE("Set point size to %f\n", tmpvalue.f);
3171 glPointSize(tmpvalue.f);
3172 checkGLcall("glPointSize(...);");
3175 case WINED3DRS_POINTSIZE_MIN :
3176 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3178 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
3179 checkGLcall("glPointParameterfEXT(...);");
3181 FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl\n");
3185 case WINED3DRS_POINTSIZE_MAX :
3186 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3188 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
3189 checkGLcall("glPointParameterfEXT(...);");
3191 FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl\n");
3195 case WINED3DRS_POINTSCALE_A :
3196 case WINED3DRS_POINTSCALE_B :
3197 case WINED3DRS_POINTSCALE_C :
3198 case WINED3DRS_POINTSCALEENABLE :
3200 /* If enabled, supply the parameters, otherwise fall back to defaults */
3201 if (This->stateBlock->renderState[WINED3DRS_POINTSCALEENABLE]) {
3202 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3203 att[0] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_A]);
3204 att[1] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_B]);
3205 att[2] = *((float*)&This->stateBlock->renderState[WINED3DRS_POINTSCALE_C]);
3207 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3208 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3209 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3211 TRACE("WINED3DRS_POINTSCALEENABLE not supported on this opengl\n");
3214 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
3215 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
3216 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
3217 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
3219 TRACE("WINED3DRS_POINTSCALEENABLE not supported, but not on either\n");
3225 case WINED3DRS_COLORWRITEENABLE :
3227 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3228 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3229 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3230 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3231 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3232 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3233 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3234 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3235 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3236 checkGLcall("glColorMask(...)");
3240 case WINED3DRS_LOCALVIEWER :
3242 GLint state = (Value) ? 1 : 0;
3243 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3244 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3248 case WINED3DRS_LASTPIXEL :
3251 TRACE("Last Pixel Drawing Enabled\n");
3253 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3258 case WINED3DRS_SOFTWAREVERTEXPROCESSING :
3261 TRACE("Software Processing Enabled\n");
3263 TRACE("Software Processing Disabled\n");
3268 /** not supported */
3269 case WINED3DRS_ZVISIBLE :
3272 return D3DERR_INVALIDCALL;
3275 /* Unhandled yet...! */
3276 case WINED3DRS_EDGEANTIALIAS :
3277 case WINED3DRS_WRAP0 :
3278 case WINED3DRS_WRAP1 :
3279 case WINED3DRS_WRAP2 :
3280 case WINED3DRS_WRAP3 :
3281 case WINED3DRS_WRAP4 :
3282 case WINED3DRS_WRAP5 :
3283 case WINED3DRS_WRAP6 :
3284 case WINED3DRS_WRAP7 :
3285 case WINED3DRS_POINTSPRITEENABLE :
3286 case WINED3DRS_MULTISAMPLEANTIALIAS :
3287 case WINED3DRS_MULTISAMPLEMASK :
3288 case WINED3DRS_PATCHEDGESTYLE :
3289 case WINED3DRS_PATCHSEGMENTS :
3290 case WINED3DRS_DEBUGMONITORTOKEN :
3291 case WINED3DRS_POSITIONORDER :
3292 case WINED3DRS_NORMALORDER :
3293 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3294 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3297 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3305 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
3306 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3307 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
3308 *pValue = This->stateBlock->renderState[State];
3312 HRESULT WINAPI IWineD3DDeviceImpl_SetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD Value) {
3313 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3315 * SetSampler is designed to allow for more than the standard up to 8 textures
3316 * and Geforce has stopped supporting more than 6 standard textures in openGL.
3317 * So I have to use ARB for Gforce. (maybe if the sampler > 4 then use ARB?)
3319 * http://developer.nvidia.com/object/General_FAQ.html#t6
3321 * There are two new settings for GForce
3323 * GL_MAX_TEXTURE_IMAGE_UNITS_ARB
3324 * and the texture one:
3325 * GL_MAX_TEXTURE_COORDS_ARB.
3326 * Ok GForce say it's ok to use glTexParameter/glGetTexParameter(...).
3333 TRACE("(%p) Sampler(%ld), Type(%d) Value(%ld)\n",This, Sampler ,Type, Value);
3335 if(Sampler > GL_LIMITS(samplers) || Sampler < 0 || Type > WINED3D_HIGHEST_SAMPLER_STATE || Type < 0) {
3336 FIXME("out of range %d %d sampler %ld type %u\n", GL_LIMITS(samplers), WINED3D_HIGHEST_SAMPLER_STATE, Sampler, Type);
3337 return D3DERR_INVALIDCALL;
3340 This->updateStateBlock->changed.samplerState[Sampler][Type] = TRUE;
3341 This->updateStateBlock->set.samplerState[Sampler][Type] = TRUE;
3342 TRACE("Setting sampler %ld %d to %ld \n", Sampler, Type, Value);
3343 This->updateStateBlock->samplerState[Sampler][Type] = Value;
3345 /* Handle recording of state blocks */
3346 if (This->isRecordingState) {
3347 TRACE("Recording... not performing anything\n");
3351 /* In addition, IDirect3DDevice9::SetSamplerState will now be used for filtering, tiling,
3352 clamping, MIPLOD, etc. This will work for up to 16 samplers.
3353 is this just GL_TEXTURE_2D or is it GL_TEXTURE_1D and GL_TEXTURE_3D as well?
3356 VTRACE(("Activating appropriate texture state %ld\n", Sampler));
3357 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3358 GLACTIVETEXTURE(Sampler);
3359 } else if (Sampler > 0) {
3360 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3366 case WINED3DSAMP_ADDRESSU : /* 1 */
3367 case WINED3DSAMP_ADDRESSV : /* 2 */
3368 case WINED3DSAMP_ADDRESSW : /* 3 */
3370 GLint wrapParm = GL_REPEAT;
3372 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3373 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3374 case D3DTADDRESS_BORDER:
3376 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3377 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3379 /* FIXME: Not right, but better */
3380 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3381 wrapParm = GL_REPEAT;
3385 case D3DTADDRESS_MIRROR:
3387 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3388 wrapParm = GL_MIRRORED_REPEAT_ARB;
3390 /* Unsupported in OpenGL pre-1.4 */
3391 TRACE("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3392 wrapParm = GL_REPEAT;
3396 case D3DTADDRESS_MIRRORONCE:
3398 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3399 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3401 TRACE("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3402 wrapParm = GL_REPEAT;
3408 /* This is for the whole context, not just the sampler,
3409 so we should warn if two states are baing set for any given scene */
3411 TRACE("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3412 wrapParm = GL_REPEAT;
3415 case WINED3DSAMP_ADDRESSU:
3416 TRACE("Setting WRAP_S for %ld to %d \n", Sampler, wrapParm);
3417 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_S, wrapParm);
3418 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3420 case WINED3DSAMP_ADDRESSV:
3421 TRACE("Setting WRAP_T for %ld to %d\n", Sampler, wrapParm);
3422 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_T, wrapParm);
3423 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3426 case WINED3DSAMP_ADDRESSW:
3427 TRACE("Setting WRAP_R for %ld to %d\n", Sampler, wrapParm);
3428 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_WRAP_R, wrapParm);
3429 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3432 break; /** stupic compilator */
3437 case WINED3DSAMP_BORDERCOLOR : /* 4 */
3440 D3DCOLORTOGLFLOAT4(Value, col);
3441 TRACE("Setting border color for %ld to %lx\n", Sampler, Value);
3442 glTexParameterfv(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_BORDER_COLOR, &col[0]);
3443 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3447 case WINED3DSAMP_MAGFILTER : /* 5 */
3449 DWORD ValueMAG = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAGFILTER];
3450 GLint realVal = GL_NEAREST;
3452 if (ValueMAG == D3DTEXF_POINT) {
3453 realVal = GL_NEAREST;
3454 } else if (ValueMAG == D3DTEXF_LINEAR) {
3455 realVal = GL_LINEAR;
3456 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3457 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3458 realVal = GL_LINEAR;
3460 FIXME("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3461 realVal = GL_NEAREST;
3464 FIXME("Unhandled WINED3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3465 realVal = GL_NEAREST;
3467 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3468 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAG_FILTER, realVal);
3469 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3471 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3473 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3474 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3475 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3476 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3477 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3482 case WINED3DSAMP_MINFILTER: /* 6 */
3483 case WINED3DSAMP_MIPFILTER: /* 7 */
3485 DWORD ValueMIN = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MINFILTER];
3486 DWORD ValueMIP = This->stateBlock->samplerState[Sampler][WINED3DSAMP_MIPFILTER];
3487 GLint realVal = GL_LINEAR;
3489 if (ValueMIN == D3DTEXF_NONE) {
3490 /* Doesn't really make sense - Windows just seems to disable
3491 mipmapping when this occurs */
3492 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3493 realVal = GL_LINEAR;
3494 } else if (ValueMIN == D3DTEXF_POINT) {
3496 if (ValueMIP == D3DTEXF_NONE) {
3497 realVal = GL_NEAREST;
3498 } else if (ValueMIP == D3DTEXF_POINT) {
3499 realVal = GL_NEAREST_MIPMAP_NEAREST;
3500 } else if (ValueMIP == D3DTEXF_LINEAR) {
3501 realVal = GL_NEAREST_MIPMAP_LINEAR;
3503 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3504 realVal = GL_NEAREST;
3506 } else if (ValueMIN == D3DTEXF_LINEAR) {
3508 if (ValueMIP == D3DTEXF_NONE) {
3509 realVal = GL_LINEAR;
3510 } else if (ValueMIP == D3DTEXF_POINT) {
3511 realVal = GL_LINEAR_MIPMAP_NEAREST;
3512 } else if (ValueMIP == D3DTEXF_LINEAR) {
3513 realVal = GL_LINEAR_MIPMAP_LINEAR;
3515 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3516 realVal = GL_LINEAR;
3518 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3519 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3520 if (ValueMIP == D3DTEXF_NONE) {
3521 realVal = GL_LINEAR_MIPMAP_LINEAR;
3522 } else if (ValueMIP == D3DTEXF_POINT) {
3523 realVal = GL_LINEAR_MIPMAP_NEAREST;
3524 } else if (ValueMIP == D3DTEXF_LINEAR) {
3525 realVal = GL_LINEAR_MIPMAP_LINEAR;
3527 FIXME("Unhandled WINED3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3528 realVal = GL_LINEAR;
3531 WARN("Trying to use ANISOTROPIC_FILTERING for WINED3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3532 realVal = GL_LINEAR;
3535 FIXME("Unhandled WINED3DTSS_MINFILTER value of %ld\n", ValueMIN);
3536 realVal = GL_LINEAR_MIPMAP_LINEAR;
3539 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3540 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MIN_FILTER, realVal);
3541 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3543 * if we just choose to use ANISOTROPIC filtering, refresh openGL state
3545 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3546 glTexParameteri(This->stateBlock->textureDimensions[Sampler], GL_TEXTURE_MAX_ANISOTROPY_EXT,
3547 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3548 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3553 case WINED3DSAMP_MIPMAPLODBIAS : /* 8 */
3555 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3557 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3558 GL_TEXTURE_LOD_BIAS_EXT,
3560 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3565 case WINED3DSAMP_MAXMIPLEVEL : /* 9 */
3568 * Not really the same, but the more apprioprate than nothing
3570 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3571 GL_TEXTURE_BASE_LEVEL,
3572 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXMIPLEVEL]);
3573 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3577 case WINED3DSAMP_MAXANISOTROPY : /* 10 */
3579 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3580 glTexParameteri(This->stateBlock->textureDimensions[Sampler],
3581 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3582 This->stateBlock->samplerState[Sampler][WINED3DSAMP_MAXANISOTROPY]);
3583 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3587 case WINED3DSAMP_SRGBTEXTURE : /* 11 */
3588 /* Per texture gamma correction, default 0 */
3589 case WINED3DSAMP_ELEMENTINDEX : /* 12 */
3590 /* When a multi-element textures is used this indicates the element, (what's a multielement texture?) */
3591 case WINED3DSAMP_DMAPOFFSET : /* 13 */
3592 /* Value of a precompiled displacement map used by the tesselator, default 0 */
3593 TRACE("Unsupported sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3597 TRACE("invalid sampler setting, Sampler=%ld, Type=%d, Value =%ld\n", Sampler, Type, Value);
3603 HRESULT WINAPI IWineD3DDeviceImpl_GetSamplerState(IWineD3DDevice *iface, DWORD Sampler, WINED3DSAMPLERSTATETYPE Type, DWORD* Value) {
3604 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3605 /** TODO: check that sampler is in range **/
3606 *Value = This->updateStateBlock->samplerState[Sampler][Type];
3607 TRACE("(%p) : Sampler %ld Type %u Returning %ld\n", This, Sampler, Type, *Value);
3612 HRESULT WINAPI IWineD3DDeviceImpl_SetScissorRect(IWineD3DDevice *iface, CONST RECT* pRect) {
3613 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3616 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3617 TRACE("(%p)Setting new Scissor Rect to %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3618 glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3623 HRESULT WINAPI IWineD3DDeviceImpl_GetScissorRect(IWineD3DDevice *iface, RECT* pRect) {
3624 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3625 GLint scissorBox[4];
3628 /** FIXME: Windows uses a top,left origin openGL uses a bottom Right? **/
3629 glGetIntegerv(GL_SCISSOR_BOX, scissorBox);
3630 pRect->left = scissorBox[1];
3631 pRect->top = scissorBox[2];
3632 pRect->right = scissorBox[1] + scissorBox[3];
3633 pRect->bottom = scissorBox[2] + scissorBox[4];
3634 TRACE("(%p)Returning a Scissor Rect of %ld:%ld-%ld:%ld\n", This, pRect->left, pRect->top, pRect->right, pRect->bottom);
3639 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration* pDecl) {
3640 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
3642 TRACE("(%p) : pDecl=%p\n", This, pDecl);
3644 /* TODO: what about recording stateblocks? */
3645 if (NULL != pDecl) {
3646 IWineD3DVertexDeclaration_AddRef(pDecl);
3648 if (NULL != This->updateStateBlock->vertexDecl) {
3649 IWineD3DVertexDeclaration_Release(This->updateStateBlock->vertexDecl);
3651 This->updateStateBlock->vertexDecl = pDecl;
3652 This->updateStateBlock->changed.vertexDecl = TRUE;
3653 This->updateStateBlock->set.vertexDecl = TRUE;
3657 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexDeclaration(IWineD3DDevice* iface, IWineD3DVertexDeclaration** ppDecl) {
3658 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3660 TRACE("(%p) : ppDecl=%p\n", This, ppDecl);
3662 *ppDecl = This->updateStateBlock->vertexDecl;
3663 if (NULL != *ppDecl) IWineD3DVertexDeclaration_AddRef(*ppDecl);
3667 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader* pShader) {
3668 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3670 static BOOL showFixmes = TRUE;
3672 This->updateStateBlock->vertexShader = pShader;
3673 This->updateStateBlock->changed.vertexShader = TRUE;
3674 This->updateStateBlock->set.vertexShader = TRUE;
3676 if(pShader == NULL) {
3677 /* clear down the shader */
3678 TRACE("Clear down the shader\n");
3681 FIXME("(%p) : stub pShader(%p)\n", This, pShader);
3688 /** FIXME: refernece counting? **/
3689 if (pShader == NULL) { /* only valid with non FVF shaders */
3690 TRACE_(d3d_shader)("(%p) : FVF Shader, pShader=%p\n", This, pShader);
3691 This->updateStateBlock->vertexShader = NULL;
3693 TRACE_(d3d_shader)("(%p) : Created shader, pShader=%p\n", This, pShader);
3694 This->updateStateBlock->vertexShader = pShader;
3697 This->updateStateBlock->changed.vertexShader = TRUE;
3698 This->updateStateBlock->set.vertexShader = TRUE;
3700 /* Handle recording of state blocks */
3701 if (This->isRecordingState) {
3702 TRACE("Recording... not performing anything\n");
3706 * TODO: merge HAL shaders context switching from prototype
3712 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShader(IWineD3DDevice *iface, IWineD3DVertexShader** ppShader) {
3713 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3714 *ppShader = This->stateBlock->vertexShader;
3715 if(*ppShader != NULL)
3716 IWineD3DVertexShader_AddRef(*ppShader);
3717 TRACE("(%p) : returning %p\n", This, *ppShader);
3721 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3722 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3724 TRACE("(%p) : stub\n", This);
3728 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3730 TRACE("(%p) : stub\n", This);
3734 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3735 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3736 TRACE("(%p) : stub\n", This);
3740 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3741 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3742 TRACE("(%p) : stub\n", This);
3746 HRESULT WINAPI IWineD3DDeviceImpl_SetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3747 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3748 TRACE("(%p) : stub\n", This);
3752 HRESULT WINAPI IWineD3DDeviceImpl_GetVertexShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3753 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3754 TRACE("(%p) : stub\n", This);
3758 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader *pShader) {
3759 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3760 TRACE("(%p) : stub\n", This);
3764 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShader(IWineD3DDevice *iface, IWineD3DPixelShader **ppShader) {
3765 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3766 TRACE("(%p) : stub\n", This);
3771 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, CONST BOOL *pConstantData, UINT BoolCount) {
3772 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3773 TRACE("(%p) : stub\n", This);
3777 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantB(IWineD3DDevice *iface, UINT StartRegister, BOOL *pConstantData, UINT BoolCount) {
3778 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3779 TRACE("(%p) : stub\n", This);
3783 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, CONST int *pConstantData, UINT Vector4iCount) {
3784 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3785 TRACE("(%p) : stub\n", This);
3789 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantI(IWineD3DDevice *iface, UINT StartRegister, int *pConstantData, UINT Vector4iCount) {
3790 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3791 TRACE("(%p) : stub\n", This);
3795 HRESULT WINAPI IWineD3DDeviceImpl_SetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, CONST float *pConstantData, UINT Vector4fCount) {
3796 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3797 TRACE("(%p) : stub\n", This);
3801 HRESULT WINAPI IWineD3DDeviceImpl_GetPixelShaderConstantF(IWineD3DDevice *iface, UINT StartRegister, float *pConstantData, UINT Vector4fCount) {
3802 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3803 TRACE("(%p) : stub\n", This);
3807 HRESULT WINAPI IWineD3DDeviceImpl_ProcessVertices(IWineD3DDevice *iface, UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IWineD3DVertexBuffer* pDestBuffer, IWineD3DVertexBuffer* pVertexDecl, DWORD Flags) {
3808 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3809 FIXME("(%p) : stub\n", This);
3814 * Get / Set Texture Stage States
3815 * TODO: Verify against dx9 definitions
3817 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3818 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3820 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3822 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3824 /* Reject invalid texture units */
3825 if (Stage >= GL_LIMITS(textures)) {
3826 TRACE("Attempt to access invalid texture rejected\n");
3827 return D3DERR_INVALIDCALL;
3830 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
3831 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
3832 This->updateStateBlock->textureState[Stage][Type] = Value;
3834 /* Handle recording of state blocks */
3835 if (This->isRecordingState) {
3836 TRACE("Recording... not performing anything\n");
3842 /* Make appropriate texture active */
3843 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3844 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3845 GLACTIVETEXTURE(Stage);
3846 } else if (Stage > 0) {
3847 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3851 case WINED3DTSS_ALPHAOP :
3852 case WINED3DTSS_COLOROP :
3855 if ((Value == D3DTOP_DISABLE) && (Type == WINED3DTSS_COLOROP)) {
3856 /* TODO: Disable by making this and all later levels disabled */
3857 glDisable(GL_TEXTURE_1D);
3858 checkGLcall("Disable GL_TEXTURE_1D");
3859 glDisable(GL_TEXTURE_2D);
3860 checkGLcall("Disable GL_TEXTURE_2D");
3861 glDisable(GL_TEXTURE_3D);
3862 checkGLcall("Disable GL_TEXTURE_3D");
3863 break; /* Don't bother setting the texture operations */
3865 /* Enable only the appropriate texture dimension */
3866 if (Type == WINED3DTSS_COLOROP) {
3867 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3868 glEnable(GL_TEXTURE_1D);
3869 checkGLcall("Enable GL_TEXTURE_1D");
3871 glDisable(GL_TEXTURE_1D);
3872 checkGLcall("Disable GL_TEXTURE_1D");
3874 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3875 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3876 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3877 checkGLcall("Enable GL_TEXTURE_2D");
3879 glEnable(GL_TEXTURE_2D);
3880 checkGLcall("Enable GL_TEXTURE_2D");
3883 glDisable(GL_TEXTURE_2D);
3884 checkGLcall("Disable GL_TEXTURE_2D");
3886 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3887 glEnable(GL_TEXTURE_3D);
3888 checkGLcall("Enable GL_TEXTURE_3D");
3890 glDisable(GL_TEXTURE_3D);
3891 checkGLcall("Disable GL_TEXTURE_3D");
3893 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3894 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3895 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3897 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3898 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3902 /* Drop through... (Except disable case) */
3903 case WINED3DTSS_COLORARG0 :
3904 case WINED3DTSS_COLORARG1 :
3905 case WINED3DTSS_COLORARG2 :
3906 case WINED3DTSS_ALPHAARG0 :
3907 case WINED3DTSS_ALPHAARG1 :
3908 case WINED3DTSS_ALPHAARG2 :
3910 BOOL isAlphaArg = (Type == WINED3DTSS_ALPHAOP || Type == WINED3DTSS_ALPHAARG1 ||
3911 Type == WINED3DTSS_ALPHAARG2 || Type == WINED3DTSS_ALPHAARG0);
3913 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP],
3914 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1],
3915 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG2],
3916 This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG0]);
3918 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP],
3919 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG1],
3920 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG2],
3921 This->stateBlock->textureState[Stage][WINED3DTSS_COLORARG0]);
3927 case WINED3DTSS_ADDRESSW :
3929 GLint wrapParm = GL_REPEAT;
3932 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3933 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3934 case D3DTADDRESS_BORDER:
3936 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3937 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3939 /* FIXME: Not right, but better */
3940 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3941 wrapParm = GL_REPEAT;
3945 case D3DTADDRESS_MIRROR:
3947 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3948 wrapParm = GL_MIRRORED_REPEAT_ARB;
3950 /* Unsupported in OpenGL pre-1.4 */
3951 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3952 wrapParm = GL_REPEAT;
3956 case D3DTADDRESS_MIRRORONCE:
3958 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3959 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3961 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3962 wrapParm = GL_REPEAT;
3968 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3969 wrapParm = GL_REPEAT;
3972 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
3973 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3974 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3978 case WINED3DTSS_TEXCOORDINDEX :
3980 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3982 /* FIXME: From MSDN: The WINED3DTSS_TCI_* flags are mutually exclusive. If you include
3983 one flag, you can still specify an index value, which the system uses to
3984 determine the texture wrapping mode.
3985 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3986 means use the vertex position (camera-space) as the input texture coordinates
3987 for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3988 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3989 to the TEXCOORDINDEX value */
3992 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3994 switch (Value & 0xFFFF0000) {
3995 case D3DTSS_TCI_PASSTHRU:
3996 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3997 glDisable(GL_TEXTURE_GEN_S);
3998 glDisable(GL_TEXTURE_GEN_T);
3999 glDisable(GL_TEXTURE_GEN_R);
4000 glDisable(GL_TEXTURE_GEN_Q);
4001 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
4004 case D3DTSS_TCI_CAMERASPACEPOSITION:
4005 /* CameraSpacePosition means use the vertex position, transformed to camera space,
4006 as the input texture coordinates for this stage's texture transformation. This
4007 equates roughly to EYE_LINEAR */
4009 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4010 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4011 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4012 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4013 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4015 glMatrixMode(GL_MODELVIEW);
4018 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4019 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4020 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4021 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4024 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
4025 glEnable(GL_TEXTURE_GEN_S);
4026 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4027 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4028 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4029 glEnable(GL_TEXTURE_GEN_T);
4030 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4031 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4032 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4033 glEnable(GL_TEXTURE_GEN_R);
4034 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4035 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
4036 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
4040 case D3DTSS_TCI_CAMERASPACENORMAL:
4042 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4043 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4044 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4045 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4046 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4047 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4049 glMatrixMode(GL_MODELVIEW);
4052 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4053 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4054 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4055 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4058 glEnable(GL_TEXTURE_GEN_S);
4059 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4060 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4061 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4062 glEnable(GL_TEXTURE_GEN_T);
4063 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4064 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4065 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4066 glEnable(GL_TEXTURE_GEN_R);
4067 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4068 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
4069 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
4074 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
4076 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
4077 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
4078 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
4079 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
4080 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
4081 TRACE("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
4083 glMatrixMode(GL_MODELVIEW);
4086 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
4087 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
4088 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
4089 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
4092 glEnable(GL_TEXTURE_GEN_S);
4093 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
4094 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4095 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4096 glEnable(GL_TEXTURE_GEN_T);
4097 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
4098 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4099 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4100 glEnable(GL_TEXTURE_GEN_R);
4101 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
4102 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
4103 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
4108 /* Unhandled types: */
4111 /* ? disable GL_TEXTURE_GEN_n ? */
4112 glDisable(GL_TEXTURE_GEN_S);
4113 glDisable(GL_TEXTURE_GEN_T);
4114 glDisable(GL_TEXTURE_GEN_R);
4115 glDisable(GL_TEXTURE_GEN_Q);
4116 FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %lx\n", Value);
4123 case WINED3DTSS_TEXTURETRANSFORMFLAGS :
4124 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);
4127 case WINED3DTSS_BUMPENVMAT00 :
4128 case WINED3DTSS_BUMPENVMAT01 :
4129 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT00, Stage, Type, Value);
4131 case WINED3DTSS_BUMPENVMAT10 :
4132 case WINED3DTSS_BUMPENVMAT11 :
4133 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - WINED3DTSS_BUMPENVMAT10, Stage, Type, Value);
4136 case WINED3DTSS_BUMPENVLSCALE :
4137 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4140 case WINED3DTSS_BUMPENVLOFFSET :
4141 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4144 case WINED3DTSS_RESULTARG :
4145 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4149 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
4150 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
4158 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, WINED3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
4159 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4160 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
4161 *pValue = This->updateStateBlock->textureState[Stage][Type];
4168 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
4170 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4171 IWineD3DBaseTexture *oldTexture;
4172 BOOL reapplyStates = TRUE;
4173 DWORD reapplyFlags = 0;
4174 INT oldTextureDimensions = -1;
4175 D3DRESOURCETYPE textureType;
4177 oldTexture = This->updateStateBlock->textures[Stage];
4178 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
4180 /* Reject invalid texture units */
4181 if (Stage >= GL_LIMITS(textures)) {
4182 TRACE("Attempt to access invalid texture rejected\n");
4183 return D3DERR_INVALIDCALL;
4186 This->updateStateBlock->set.textures[Stage] = TRUE;
4187 This->updateStateBlock->changed.textures[Stage] = TRUE;
4188 This->updateStateBlock->textures[Stage] = pTexture;
4190 /* Handle recording of state blocks */
4191 if (This->isRecordingState) {
4192 TRACE("Recording... not performing anything\n");
4196 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
4200 /* Make appropriate texture active */
4201 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
4202 GLACTIVETEXTURE(Stage);
4204 } else if (Stage>0) {
4205 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
4208 /** NOTE: MSDN says that setTexture increases the reference count,
4209 * and the the application nust set the texture back to null (or have a leaky application),
4210 * This means we should pass the refcount upto the parent
4211 *******************************/
4212 if (NULL != This->updateStateBlock->textures[Stage]) {
4213 IUnknown *textureParent;
4214 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[Stage], (IUnknown **)&textureParent);
4215 /** NOTE: GetParent will increase the ref count for me, I won't clean up untill the texture is set to NULL **/
4218 if (NULL != oldTexture) {
4219 IUnknown *textureParent;
4220 IWineD3DBaseTexture_GetParent(oldTexture, (IUnknown **)&textureParent);
4221 IUnknown_Release(textureParent);
4222 IUnknown_Release(textureParent); /** NOTE: Twice because GetParent adds a ref **/
4227 if (NULL != pTexture) {
4228 /* Now setup the texture appropraitly */
4229 textureType = IWineD3DBaseTexture_GetType(pTexture);
4231 if (textureType == D3DRTYPE_TEXTURE) {
4233 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4234 TRACE("Skipping setting texture as old == new\n");
4235 reapplyStates = FALSE;
4239 /* Standard 2D texture */
4240 TRACE("Standard 2d texture\n");
4241 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
4243 /* Load up the texture now */
4244 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
4247 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
4249 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4250 TRACE("Skipping setting texture as old == new\n");
4251 reapplyStates = FALSE;
4255 /* Standard 3D (volume) texture */
4256 TRACE("Standard 3d texture\n");
4257 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
4259 /* Load up the texture now */
4260 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
4263 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
4265 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
4266 TRACE("Skipping setting texture as old == new\n");
4267 reapplyStates = FALSE;
4271 /* Standard Cube texture */
4272 TRACE("Standard Cube texture\n");
4273 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
4275 /* Load up the texture now */
4276 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
4280 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
4285 TRACE("Setting to no texture (ie default texture)\n");
4286 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
4287 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
4288 checkGLcall("glBindTexture");
4289 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
4292 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
4293 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
4295 glDisable(oldTextureDimensions);
4296 checkGLcall("Disable oldTextureDimensions");
4298 if (This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP] != D3DTOP_DISABLE) {
4299 glEnable(This->updateStateBlock->textureDimensions[Stage]);
4300 checkGLcall("glEnable new texture dimensions");
4303 /* If Alpha arg1 is texture then handle the special case when there changes between a
4304 texture and no texture - See comments in set_tex_op */
4305 if ((This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
4306 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
4308 reapplyFlags |= REAPPLY_ALPHAOP;
4313 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
4314 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
4315 if (reapplyStates) {
4316 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
4320 TRACE("Texture now fully setup\n");
4325 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
4326 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4327 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
4328 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
4330 IWineD3DBaseTexture_AddRef(*ppTexture);
4337 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
4338 IWineD3DSurface** ppBackBuffer) {
4339 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4340 IWineD3DSwapChain *swapChain;
4343 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
4345 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapChain);
4347 hr = IWineD3DSwapChain_GetBackBuffer(swapChain, BackBuffer, Type, ppBackBuffer);
4348 IWineD3DSwapChain_Release(swapChain);
4350 *ppBackBuffer = NULL;
4355 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, WINED3DCAPS* pCaps) {
4356 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4357 WARN("(%p) : stub, calling idirect3d for now\n", This);
4358 return IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
4361 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
4362 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4363 IWineD3DSwapChain *swapChain;
4366 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4368 hr = IWineD3DSwapChain_GetDisplayMode(swapChain, pMode);
4369 IWineD3DSwapChain_Release(swapChain);
4371 FIXME("(%p) Error getting display mode\n", This);
4376 * Stateblock related functions
4379 HRESULT WINAPI IWineD3DDeviceImpl_BeginStateBlock(IWineD3DDevice *iface) {
4380 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4381 IWineD3DStateBlockImpl *object;
4382 TRACE("(%p)", This);
4383 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
4384 if(NULL == object ) {
4385 FIXME("(%p)Error allocating memory for stateblock\n", This);
4386 return E_OUTOFMEMORY;
4388 TRACE("(%p) creted object %p\n", This, object);
4389 object->wineD3DDevice= This;
4390 /** FIXME: object->parent = parent; **/
4391 object->parent = NULL;
4392 object->blockType = WINED3DSBT_ALL;
4394 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
4396 IWineD3DStateBlock_Release((IWineD3DStateBlock*)This->updateStateBlock);
4397 This->updateStateBlock = object;
4398 This->isRecordingState = TRUE;
4400 TRACE("(%p) recording stateblock %p\n",This , object);
4404 HRESULT WINAPI IWineD3DDeviceImpl_EndStateBlock(IWineD3DDevice *iface, IWineD3DStateBlock** ppStateBlock) {
4405 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4407 if (!This->isRecordingState) {
4408 FIXME("(%p) not recording! returning error\n", This);
4409 *ppStateBlock = NULL;
4410 return D3DERR_INVALIDCALL;
4413 *ppStateBlock = (IWineD3DStateBlock*)This->updateStateBlock;
4414 This->isRecordingState = FALSE;
4415 This->updateStateBlock = This->stateBlock;
4416 IWineD3DStateBlock_AddRef((IWineD3DStateBlock*)This->updateStateBlock);
4417 /* IWineD3DStateBlock_AddRef(*ppStateBlock); don't need to do this, since we should really just release UpdateStateBlock first */
4418 TRACE("(%p) returning token (ptr to stateblock) of %p\n", This, *ppStateBlock);
4423 * Scene related functions
4425 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
4426 /* At the moment we have no need for any functionality at the beginning
4428 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4429 TRACE("(%p) : stub\n", This);
4433 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
4434 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4435 TRACE("(%p)\n", This);
4437 /* We only have to do this if we need to read the, swapbuffers performs a flush for us */
4439 checkGLcall("glFlush");
4441 TRACE("End Scene\n");
4442 if(This->renderTarget != NULL) {
4444 /* If the container of the rendertarget is a texture then we need to save the data from the pbuffer */
4445 IUnknown *targetContainer = NULL;
4446 if (D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DBaseTexture, (void **)&targetContainer)
4447 || D3D_OK == IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DDevice, (void **)&targetContainer)) {
4448 TRACE("(%p) : Texture rendertarget %p\n", This ,This->renderTarget);
4449 /** always dirtify for now. we must find a better way to see that surface have been modified
4450 (Modifications should will only occur via draw-primitive, but we do need better locking
4451 switching to render-to-texture should remove the overhead though.
4453 IWineD3DSurface_SetPBufferState(This->renderTarget, TRUE /* inPBuffer */, FALSE /* inTexture */);
4454 IWineD3DSurface_AddDirtyRect(This->renderTarget, NULL);
4455 IWineD3DSurface_PreLoad(This->renderTarget);
4456 IWineD3DSurface_SetPBufferState(This->renderTarget, FALSE /* inPBuffer */, FALSE /* inTexture */);
4457 IUnknown_Release(targetContainer);
4460 This->sceneEnded = TRUE;
4465 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
4466 CONST RECT* pSourceRect, CONST RECT* pDestRect,
4467 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
4468 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4469 IWineD3DSwapChain *swapChain = NULL;
4471 int swapchains = IWineD3DDeviceImpl_GetNumberOfSwapChains(iface);
4473 TRACE("(%p) Presenting the frame\n", This);
4475 for(i = 0 ; i < swapchains ; i ++) {
4477 IWineD3DDeviceImpl_GetSwapChain(iface, i , (IWineD3DSwapChain **)&swapChain);
4478 TRACE("presentinng chain %d, %p\n", i, swapChain);
4479 IWineD3DSwapChain_Present(swapChain, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, 0);
4480 IWineD3DSwapChain_Release(swapChain);
4486 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
4487 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
4488 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4490 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
4491 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
4492 when the depth-buffer format does not contain stencil buffer information, this method fails. */
4493 GLbitfield glMask = 0;
4494 GLboolean old_ztest;
4495 GLfloat old_z_clear_value;
4496 GLint old_stencil_clear_value;
4497 GLfloat old_color_clear_value[4];
4499 CONST D3DRECT* curRect;
4501 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
4502 Count, pRects, Flags, Z, Stencil);
4506 glEnable(GL_SCISSOR_TEST);
4507 checkGLcall("glEnable GL_SCISSOR_TEST");
4509 if (Count > 0 && pRects) {
4515 /* Only set the values up once, as they are not changing */
4516 if (Flags & D3DCLEAR_STENCIL) {
4517 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
4518 glClearStencil(Stencil);
4519 checkGLcall("glClearStencil");
4520 glMask = glMask | GL_STENCIL_BUFFER_BIT;
4521 glStencilMask(0xFFFFFFFF);
4524 if (Flags & D3DCLEAR_ZBUFFER) {
4525 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
4526 glDepthMask(GL_TRUE);
4527 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
4529 checkGLcall("glClearDepth");
4530 glMask = glMask | GL_DEPTH_BUFFER_BIT;
4533 if (Flags & D3DCLEAR_TARGET) {
4534 TRACE("Clearing screen with glClear to color %lx\n", Color);
4535 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
4536 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
4537 ((Color >> 8) & 0xFF) / 255.0f,
4538 ((Color >> 0) & 0xFF) / 255.0f,
4539 ((Color >> 24) & 0xFF) / 255.0f);
4540 checkGLcall("glClearColor");
4542 /* Clear ALL colors! */
4543 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
4544 glMask = glMask | GL_COLOR_BUFFER_BIT;
4547 /* Now process each rect in turn */
4548 for (i = 0; i < Count || i == 0; i++) {
4551 /* Note gl uses lower left, width/height */
4552 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
4553 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
4554 curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4555 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4556 glScissor(curRect->x1, (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - curRect->y2),
4557 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
4558 checkGLcall("glScissor");
4560 glScissor(This->stateBlock->viewport.X,
4561 (((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
4562 This->stateBlock->viewport.Width,
4563 This->stateBlock->viewport.Height);
4564 checkGLcall("glScissor");
4567 /* Clear the selected rectangle (or full screen) */
4569 checkGLcall("glClear");
4571 /* Step to the next rectangle */
4572 if (curRect) curRect = curRect + sizeof(D3DRECT);
4575 /* Restore the old values (why..?) */
4576 if (Flags & D3DCLEAR_STENCIL) {
4577 glClearStencil(old_stencil_clear_value);
4578 glStencilMask(This->stateBlock->renderState[WINED3DRS_STENCILWRITEMASK]);
4580 if (Flags & D3DCLEAR_ZBUFFER) {
4581 glDepthMask(old_ztest);
4582 glClearDepth(old_z_clear_value);
4584 if (Flags & D3DCLEAR_TARGET) {
4585 glClearColor(old_color_clear_value[0],
4586 old_color_clear_value[1],
4587 old_color_clear_value[2],
4588 old_color_clear_value[3]);
4589 glColorMask(This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
4590 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
4591 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
4592 This->stateBlock->renderState[WINED3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
4595 glDisable(GL_SCISSOR_TEST);
4596 checkGLcall("glDisable");
4605 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
4606 UINT PrimitiveCount) {
4608 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4609 This->stateBlock->streamIsUP = FALSE;
4611 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
4612 debug_d3dprimitivetype(PrimitiveType),
4613 StartVertex, PrimitiveCount);
4614 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
4619 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
4620 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
4621 D3DPRIMITIVETYPE PrimitiveType,
4622 INT baseVIndex, UINT minIndex,
4623 UINT NumVertices,UINT startIndex,UINT primCount) {
4625 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4627 IWineD3DIndexBuffer *pIB;
4628 D3DINDEXBUFFER_DESC IdxBufDsc;
4630 pIB = This->stateBlock->pIndexData;
4631 This->stateBlock->streamIsUP = FALSE;
4633 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
4634 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4635 minIndex, NumVertices, startIndex, baseVIndex, primCount);
4637 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
4638 if (IdxBufDsc.Format == WINED3DFMT_INDEX16) {
4644 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
4645 startIndex, idxStride,
4646 ((IWineD3DIndexBufferImpl *) pIB)->resource.allocatedMemory,
4652 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4653 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
4654 UINT VertexStreamZeroStride) {
4655 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4657 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
4658 debug_d3dprimitivetype(PrimitiveType),
4659 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
4661 if (This->stateBlock->streamSource[0] != NULL) {
4662 IUnknown *vertexBufferParent;
4663 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4664 IUnknown_Release(vertexBufferParent);
4665 IUnknown_Release(vertexBufferParent);
4668 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4669 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4670 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4671 This->stateBlock->streamIsUP = TRUE;
4672 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
4673 This->stateBlock->streamStride[0] = 0;
4674 This->stateBlock->streamSource[0] = NULL;
4676 /*stream zero settings set to null at end, as per the msdn */
4680 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
4681 UINT MinVertexIndex,
4682 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
4683 WINED3DFORMAT IndexDataFormat, CONST void* pVertexStreamZeroData,
4684 UINT VertexStreamZeroStride) {
4686 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4688 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
4689 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
4690 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
4691 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
4693 if (IndexDataFormat == WINED3DFMT_INDEX16) {
4699 if (This->stateBlock->streamSource[0] != NULL) {
4700 IUnknown *vertexBufferParent;
4701 IWineD3DVertexBuffer_GetParent(This->stateBlock->streamSource[0], &vertexBufferParent);
4702 This->stateBlock->streamSource[0] = NULL;
4703 IUnknown_Release(vertexBufferParent);
4704 IUnknown_Release(vertexBufferParent);
4707 if (This->stateBlock->pIndexData) {
4708 IUnknown *indexBufferParent;
4709 IWineD3DIndexBuffer_GetParent(This->stateBlock->pIndexData, &indexBufferParent);
4710 This->stateBlock->pIndexData = NULL;
4711 IUnknown_Release(indexBufferParent);
4712 IUnknown_Release(indexBufferParent);
4715 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
4716 This->stateBlock->streamSource[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
4717 This->stateBlock->streamIsUP = TRUE;
4718 This->stateBlock->streamStride[0] = VertexStreamZeroStride;
4720 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
4722 /* stream zero settings set to null at end as per the msdn */
4723 This->stateBlock->streamSource[0] = NULL;
4724 This->stateBlock->streamStride[0] = 0;
4729 /* Yet another way to update a texture, some apps use this to load default textures instead of using surface/texture lock/unlock */
4730 HRESULT WINAPI IWineD3DDeviceImpl_UpdateTexture (IWineD3DDevice *iface, IWineD3DBaseTexture *pSourceTexture, IWineD3DBaseTexture *pDestinationTexture){
4731 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4732 D3DRESOURCETYPE sourceType;
4733 D3DRESOURCETYPE destinationType;
4734 IWineD3DTextureImpl *pDestTexture = (IWineD3DTextureImpl *)pDestinationTexture;
4735 IWineD3DTextureImpl *pSrcTexture = (IWineD3DTextureImpl *)pSourceTexture;
4738 sourceType = IWineD3DBaseTexture_GetType(pSourceTexture);
4739 destinationType = IWineD3DBaseTexture_GetType(pDestinationTexture);
4740 if(sourceType != D3DRTYPE_TEXTURE && destinationType != D3DRTYPE_TEXTURE){
4741 FIXME("(%p) Only D3DRTYPE_TEXTURE to D3DRTYPE_TEXTURE supported\n", This);
4742 return D3DERR_INVALIDCALL;
4744 TRACE("(%p) Source %p Destination %p\n", This, pSourceTexture, pDestinationTexture);
4746 /** TODO: Get rid of the casts to IWineD3DBaseTextureImpl
4747 repalce surfaces[x] with GetSurfaceLevel, or GetCubeMapSurface etc..
4748 think about moving the code into texture, and adding a member to base texture to occomplish this **/
4750 /* Make sure that the destination texture is loaded */
4751 IWineD3DBaseTexture_PreLoad(pDestinationTexture);
4752 TRACE("Loading source texture\n");
4754 if(pSrcTexture->surfaces[0] == NULL || pDestTexture->surfaces[0] == NULL){
4755 FIXME("(%p) Texture src %p or dest %p has not surface %p %p\n", This, pSrcTexture, pDestTexture,
4756 pSrcTexture->surfaces[0], pDestTexture->surfaces[0]);
4759 if(((IWineD3DSurfaceImpl *)pSrcTexture->surfaces[0])->resource.pool != D3DPOOL_SYSTEMMEM ||
4760 ((IWineD3DSurfaceImpl *)pDestTexture->surfaces[0])->resource.pool != D3DPOOL_DEFAULT){
4762 FIXME("(%p) source %p must be SYSTEMMEM and dest %p must be DEFAULT\n",This, pSrcTexture, pDestTexture);
4763 return D3DERR_INVALIDCALL;
4765 /** TODO: check that both textures have the same number of levels **/
4767 if(IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) !=IWineD3DBaseTexture_GetLevelCount(pSourceTexture))
4768 return D3DERR_INVALIDCALL;
4770 /** TODO: move this code into baseTexture? device should never touch impl*'s **/
4771 for(i = 0 ; i < IWineD3DBaseTexture_GetLevelCount(pDestinationTexture) ; i++){
4772 IWineD3DDevice_UpdateSurface(iface, pSrcTexture->surfaces[i], NULL, pDestTexture->surfaces[i], NULL);
4778 HRESULT WINAPI IWineD3DDeviceImpl_StretchRect(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface,
4779 CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface,
4780 CONST RECT* pDestRect, D3DTEXTUREFILTERTYPE Filter) {
4781 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4783 TRACE("(%p) : stub\n", This);
4786 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTargetData(IWineD3DDevice *iface, IWineD3DSurface *pRenderTarget, IWineD3DSurface *pSurface) {
4787 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4789 TRACE("(%p) : stub\n", This);
4793 HRESULT WINAPI IWineD3DDeviceImpl_GetFrontBufferData(IWineD3DDevice *iface,UINT iSwapChain, IWineD3DSurface *pDestSurface) {
4794 IWineD3DSwapChain *swapChain;
4796 hr = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, (IWineD3DSwapChain **)&swapChain);
4798 hr = IWineD3DSwapChain_GetFrontBufferData(swapChain, pDestSurface);
4799 IWineD3DSwapChain_Release(swapChain);
4804 HRESULT WINAPI IWineD3DDeviceImpl_ValidateDevice(IWineD3DDevice *iface, DWORD* pNumPasses) {
4805 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4806 /* return a sensible default */
4808 FIXME("(%p) : stub\n", This);
4812 HRESULT WINAPI IWineD3DDeviceImpl_SetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
4813 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4814 FIXME("(%p) : stub\n", This);
4818 HRESULT WINAPI IWineD3DDeviceImpl_GetPaletteEntries(IWineD3DDevice *iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
4819 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4820 FIXME("(%p) : stub\n", This);
4824 HRESULT WINAPI IWineD3DDeviceImpl_SetCurrentTexturePalette(IWineD3DDevice *iface, UINT PaletteNumber) {
4825 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4826 FIXME("(%p) : stub\n", This);
4830 HRESULT WINAPI IWineD3DDeviceImpl_GetCurrentTexturePalette(IWineD3DDevice *iface, UINT* PaletteNumber) {
4831 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4832 FIXME("(%p) : stub\n", This);
4836 HRESULT WINAPI IWineD3DDeviceImpl_SetSoftwareVertexProcessing(IWineD3DDevice *iface, BOOL bSoftware) {
4837 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4838 FIXME("(%p) : stub\n", This);
4843 BOOL WINAPI IWineD3DDeviceImpl_GetSoftwareVertexProcessing(IWineD3DDevice *iface) {
4844 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4845 FIXME("(%p) : stub\n", This);
4850 HRESULT WINAPI IWineD3DDeviceImpl_GetRasterStatus(IWineD3DDevice *iface, UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus) {
4851 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4853 pRasterStatus->InVBlank = TRUE;
4854 pRasterStatus->ScanLine = 0;
4855 FIXME("(%p) : stub\n", This);
4860 HRESULT WINAPI IWineD3DDeviceImpl_SetNPatchMode(IWineD3DDevice *iface, float nSegments) {
4861 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4862 static BOOL showfixmes = TRUE;
4863 if(nSegments != 0.0f) {
4865 FIXME("(%p) : stub nSegments(%f)\n", This, nSegments);
4872 float WINAPI IWineD3DDeviceImpl_GetNPatchMode(IWineD3DDevice *iface) {
4873 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
4874 static BOOL showfixmes = TRUE;
4876 FIXME("(%p) : stub returning(%f)\n", This, 0.0f);
4883 HRESULT WINAPI IWineD3DDeviceImpl_UpdateSurface(IWineD3DDevice *iface, IWineD3DSurface *pSourceSurface, CONST RECT* pSourceRect, IWineD3DSurface *pDestinationSurface, CONST POINT* pDestPoint) {
4884 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
4885 /** TODO: remove casts to IWineD3DSurfaceImpl
4886 * NOTE: move code to surface to accomplish this
4887 ****************************************/
4888 IWineD3DSurfaceImpl *pSrcSurface = (IWineD3DSurfaceImpl *)pSourceSurface;
4889 int srcWidth, srcHeight;
4890 unsigned int srcSurfaceWidth, srcSurfaceHeight, destSurfaceWidth, destSurfaceHeight;
4891 WINED3DFORMAT destFormat, srcFormat;
4893 int destLeft, destTop;
4894 D3DPOOL srcPool, destPool;
4896 int rowoffset = 0; /* how many bytes to add onto the end of a row to wraparound to the beginning of the next */
4897 glDescriptor *glDescription = NULL;
4898 GLenum textureDimensions = GL_TEXTURE_2D;
4899 IWineD3DBaseTexture *baseTexture;
4901 WINED3DSURFACE_DESC winedesc;
4903 memset(&winedesc, 0, sizeof(winedesc));
4904 winedesc.Width = &srcSurfaceWidth;
4905 winedesc.Height = &srcSurfaceHeight;
4906 winedesc.Pool = &srcPool;
4907 winedesc.Format = &srcFormat;
4909 IWineD3DSurface_GetDesc(pSourceSurface, &winedesc);
4911 winedesc.Width = &destSurfaceWidth;
4912 winedesc.Height = &destSurfaceHeight;
4913 winedesc.Pool = &destPool;
4914 winedesc.Format = &destFormat;
4915 winedesc.Size = &destSize;
4917 IWineD3DSurface_GetDesc(pDestinationSurface, &winedesc);
4919 if(srcPool != D3DPOOL_SYSTEMMEM || destPool != D3DPOOL_DEFAULT){
4920 FIXME("source %p must be SYSTEMMEM and dest %p must be DEFAULT\n", pSourceSurface, pDestinationSurface);
4921 return D3DERR_INVALIDCALL;
4923 /* TODO: change this to use bindTexture */
4924 /* Make sure the surface is loaded and upto date */
4925 IWineD3DSurface_PreLoad(pDestinationSurface);
4927 IWineD3DSurface_GetGlDesc(pDestinationSurface, &glDescription);
4931 /* this needs to be done in lines if the sourceRect != the sourceWidth */
4932 srcWidth = pSourceRect ? pSourceRect->right - pSourceRect->left : srcSurfaceWidth;
4933 srcHeight = pSourceRect ? pSourceRect->top - pSourceRect->bottom : srcSurfaceHeight;
4934 destLeft = pDestPoint ? pDestPoint->x : 0;
4935 destTop = pDestPoint ? pDestPoint->y : 0;
4938 /* This function doesn't support compressed textures
4939 the pitch is just bytesPerPixel * width */
4941 if(srcWidth != srcSurfaceWidth || (pSourceRect != NULL && pSourceRect->left != 0) ){
4942 rowoffset = (srcSurfaceWidth - srcWidth) * pSrcSurface->bytesPerPixel;
4943 offset += pSourceRect->left * pSrcSurface->bytesPerPixel;
4944 /* TODO: do we ever get 3bpp?, would a shift and an add be quicker than a mul (well maybe a cycle or two) */
4946 /* TODO DXT formats */
4948 if(pSourceRect != NULL && pSourceRect->top != 0){
4949 offset += pSourceRect->top * srcWidth * pSrcSurface->bytesPerPixel;
4951 TRACE("(%p) glTexSubImage2D, Level %d, left %d, top %d, width %d, height %d , ftm %d, type %d, memory %p\n"
4953 ,glDescription->level
4958 ,glDescription->glFormat
4959 ,glDescription->glType
4960 ,IWineD3DSurface_GetData(pSourceSurface)
4964 if (IWineD3DSurface_GetData(pSourceSurface) == NULL) {
4965 /* need to lock the surface to get the data */
4966 FIXME("Surfaces has no allocated memory, but should be an in memory only surface\n");
4968 /* TODO: Cube and volume support */
4970 /* not a whole row so we have to do it a line at a time */
4972 /* hopefully using pointer addtion will be quicker than using a point + j * rowoffset */
4973 unsigned char* data =((unsigned char *)IWineD3DSurface_GetData(pSourceSurface)) + offset;
4975 for(j = destTop ; j < (srcHeight + destTop) ; j++){
4977 glTexSubImage2D(glDescription->target
4978 ,glDescription->level
4983 ,glDescription->glFormat
4984 ,glDescription->glType
4985 ,data/* could be quicker using */
4990 } else { /* Full width, so just write out the whole texture */
4992 if (WINED3DFMT_DXT1 == destFormat ||
4993 WINED3DFMT_DXT3 == destFormat ||
4994 WINED3DFMT_DXT5 == destFormat) {
4995 if (GL_SUPPORT(EXT_TEXTURE_COMPRESSION_S3TC)) {
4996 if (destSurfaceHeight != srcHeight || destSurfaceWidth != srcWidth) {
4997 /* FIXME: The easy way to do this is lock the destination, and copy the bits accross */
4998 FIXME("Updating part of a compressed texture is not supported at the moment\n");
4999 } if (destFormat != srcFormat) {
5000 FIXME("Updating mixed format compressed texture is not curretly support\n");
5002 GL_EXTCALL(glCompressedTexImage2DARB)(glDescription->target,
5003 glDescription->level,
5004 glDescription->glFormatInternal,
5009 IWineD3DSurface_GetData(pSourceSurface));
5012 FIXME("Attempting to update a DXT compressed texture without hardware support\n");
5017 /* some applications cannot handle odd pitches returned by soft non-power2, so we have
5018 to repack the data from pow2Width/Height to expected Width,Height, this makes the
5019 data returned by GetData non-power2 width/height with hardware non-power2
5020 pow2Width/height are set to surface width height, repacking isn't needed so it
5021 doesn't matter which function gets called. */
5022 glTexSubImage2D(glDescription->target
5023 ,glDescription->level
5028 ,glDescription->glFormat
5029 ,glDescription->glType
5030 ,IWineD3DSurface_GetData(pSourceSurface)
5035 checkGLcall("glTexSubImage2D");
5036 /* I only need to look up baseTexture here, so it may be a good idea to hava a GL_TARGET ->
5037 * GL_DIMENSIONS lookup, or maybe store the dimensions on the surface (but that's making the
5038 * surface bigger than it needs to be hmm.. */
5039 if (D3D_OK == IWineD3DSurface_GetContainer(pDestinationSurface, &IID_IWineD3DBaseTexture, (void **)&baseTexture)) {
5040 textureDimensions = IWineD3DBaseTexture_GetTextureDimensions(baseTexture);
5041 IWineD3DBaseTexture_Release(baseTexture);
5044 glDisable(textureDimensions); /* This needs to be managed better.... */
5050 /* Implementation details at http://developer.nvidia.com/attach/6494
5052 http://oss.sgi.com/projects/ogl-sample/registry/NV/evaluators.txt
5053 hmm.. no longer supported use
5054 OpenGL evaluators or tessellate surfaces within your application.
5057 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawRectPatch.asp */
5058 HRESULT WINAPI IWineD3DDeviceImpl_DrawRectPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
5059 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5060 TRACE("(%p) Handle(%d) noSegs(%p) rectpatch(%p) \n", This, Handle, pNumSegs, pRectPatchInfo);
5061 FIXME("(%p) : Stub\n", This);
5066 /* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/interfaces/idirect3ddevice9/DrawTriPatch.asp */
5067 HRESULT WINAPI IWineD3DDeviceImpl_DrawTriPatch(IWineD3DDevice *iface, UINT Handle, CONST float* pNumSegs, CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
5068 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5069 TRACE("(%p) Handle(%d) noSegs(%p) tripatch(%p) \n", This, Handle, pNumSegs, pTriPatchInfo);
5070 FIXME("(%p) : Stub\n", This);
5074 HRESULT WINAPI IWineD3DDeviceImpl_DeletePatch(IWineD3DDevice *iface, UINT Handle) {
5075 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5076 TRACE("(%p) Handle(%d)\n", This, Handle);
5077 FIXME("(%p) : Stub\n", This);
5081 HRESULT WINAPI IWineD3DDeviceImpl_ColorFill(IWineD3DDevice *iface, IWineD3DSurface *pSurface, CONST D3DRECT* pRect, D3DCOLOR color) {
5082 /* I couldn't find a 'really' quick way of doing this in openGl so here goes
5083 fill a surface with a block of color! */
5084 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5085 /* TODO: get rid of the use of IWineD3DSurfaceImpl, move code into surface.c */
5086 IWineD3DSurfaceImpl *surface = (IWineD3DSurfaceImpl *)pSurface;
5087 IWineD3DSwapChainImpl *container = NULL;
5088 BOOL isRenderTarget = FALSE;
5089 unsigned int width, height;
5090 unsigned int top, left;
5093 TRACE("(%p) Colour fill Surface: %p rect: %p color: %ld\n", This, pSurface, pRect, color);
5094 if (surface->resource.pool != D3DPOOL_DEFAULT) {
5095 FIXME("call to colorfill with non D3DPOOL_DEFAULT surface\n");
5096 return D3DERR_INVALIDCALL;
5099 /* TODO: get rid of IWineD3DSwapChainImpl reference, a 'context' manager may help with this */
5100 if (D3D_OK == IWineD3DSurface_GetContainer(pSurface, &IID_IWineD3DSwapChain, (void **)&container) || pSurface == This->renderTarget) {
5101 if (D3DUSAGE_RENDERTARGET & surface->resource.usage) {
5102 /* TODO: make sure we set everything back to the way it was, and context management!
5103 glGetIntegerv(GL_READ_BUFFER, &prev_read);
5104 vcheckGLcall("glIntegerv");
5105 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
5106 vcheckGLcall("glIntegerv");
5108 TRACE("Color fill to render targets may cause some graphics issues\n");
5109 if (pSurface == container->frontBuffer) {
5110 glDrawBuffer(GL_FRONT);
5112 glDrawBuffer(GL_BACK);
5115 if (D3DUSAGE_DEPTHSTENCIL & surface->resource.usage) {
5116 FIXME("colouring of depth_stencil? %p buffers is not yet supported? %ld \n", surface, surface->resource.usage);
5118 FIXME("(%p) : Regression %ld %p %p\n", This, surface->resource.usage, pSurface, This->renderTarget);
5120 if (container != NULL) {
5121 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5123 /* we can use GL_STENCIL_INDEX etc...*/
5126 if (container != NULL) {
5127 IWineD3DSwapChain_Release((IWineD3DSwapChain *)container);
5129 isRenderTarget = TRUE;
5131 /* TODO: drawing to GL_FRONT and GL_BACK */
5132 /* TODO: see if things can be speeded up by using the correct
5133 * colour model of the target texture from the start (16 bit graphics on 32 X are slow anyway!) */
5134 if (pRect == NULL) {
5137 width = surface->currentDesc.Width;
5138 height = surface->currentDesc.Height;
5142 width = pRect->x2 - left;
5143 height = pRect->y2 - top;
5146 data = HeapAlloc(GetProcessHeap(), 0, 4 * width);
5147 /* Create a 'line' of color color, in the correct format for the surface */
5148 for (u = 0 ; u < width ; u ++) {
5153 if (isRenderTarget == FALSE) {
5154 glDescriptor *glDesc;
5155 IWineD3DSurface_PreLoad(pSurface);
5157 /* draw a block of the coloured line on the sufrace */
5158 IWineD3DSurface_GetGlDesc(pSurface, &glDesc);
5159 for (v = 0 ; v< height;v++) {
5160 glTexSubImage2D(glDesc->target
5161 ,glDesc->level /* level */
5171 checkGLcall("glTexSubImage2D");
5173 glDisable(glDesc->target);
5175 /** FIXME: Using GLClear may be faster **/
5176 glRasterPos2i(left, top);
5177 glPixelZoom((float)width ,(float)height);
5178 glDrawPixels(1, 1, GL_RGBA, GL_UNSIGNED_BYTE, data);
5179 checkGLcall("glDrawPixels");
5181 HeapFree(GetProcessHeap(), 0, data);
5187 /* rendertarget and deptth stencil functions */
5188 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderTarget(IWineD3DDevice* iface,DWORD RenderTargetIndex, IWineD3DSurface **ppRenderTarget) {
5189 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5191 /* FIXME: Implelent RenderTargetIndex >0 */
5192 if(RenderTargetIndex > 0)
5193 FIXME("(%p) : RenderTargetIndex %ld >0 not currently supported\n", This, RenderTargetIndex);
5195 *ppRenderTarget = This->renderTarget;
5196 TRACE("(%p) : RenderTarget %ld Index returning %p\n", This, RenderTargetIndex, *ppRenderTarget);
5197 /* Note inc ref on returned surface */
5198 if(*ppRenderTarget != NULL)
5199 IWineD3DSurface_AddRef(*ppRenderTarget);
5203 HRESULT WINAPI IWineD3DDeviceImpl_GetDepthStencilSurface(IWineD3DDevice* iface, IWineD3DSurface **ppZStencilSurface) {
5204 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5205 *ppZStencilSurface = This->depthStencilBuffer;
5206 TRACE("(%p) : zStencilSurface returning %p\n", This, *ppZStencilSurface);
5208 if(*ppZStencilSurface != NULL) {
5209 /* Note inc ref on returned surface */
5210 IWineD3DSurface_AddRef(*ppZStencilSurface);
5215 /* internal static helper functions */
5216 HRESULT WINAPI static IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5217 IWineD3DSurface *RenderSurface);
5219 HRESULT WINAPI static IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain);
5221 HRESULT WINAPI static IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context);
5223 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderTarget(IWineD3DDevice *iface, DWORD RenderTargetIndex, IWineD3DSurface *pRenderTarget) {
5224 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5225 HRESULT hr = D3D_OK;
5226 WINED3DVIEWPORT viewport;
5228 TRACE("(%p) Swapping rendertarget\n",This);
5229 if (RenderTargetIndex > 0) {
5230 FIXME("(%p) Render targets other than the first are not supported\n",This);
5231 RenderTargetIndex = 0;
5234 /* MSDN says that null disables the render target
5235 but a device must always be associated with a render target
5236 nope MSDN says that we return invalid call to a null rendertarget with an index of 0
5238 see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/programmingguide/AdvancedTopics/PixelPipe/MultipleRenderTarget.asp
5241 if (RenderTargetIndex == 0 && pRenderTarget == NULL) {
5242 FIXME("Trying to set render target 0 to NULL\n");
5243 return D3DERR_INVALIDCALL;
5245 /* TODO: replace Impl* usage with interface usage */
5246 if (!((IWineD3DSurfaceImpl *)pRenderTarget)->resource.usage & D3DUSAGE_RENDERTARGET) {
5247 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);
5248 return D3DERR_INVALIDCALL;
5250 /** TODO: check that the depth stencil format matches the render target, this is only done in debug
5251 * builds, but I think wine counts as a 'debug' build for now.
5252 ******************************/
5253 /* If we are trying to set what we already have, don't bother */
5254 if (pRenderTarget == This->renderTarget) {
5255 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5257 /* Otherwise, set the render target up */
5259 if (FALSE == This->sceneEnded) {
5260 IWineD3DDevice_EndScene(iface);
5262 TRACE("clearing renderer\n");
5263 /* IWineD3DDeviceImpl_CleanRender(iface); */
5264 /* OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5265 depending on the renter target implementation being used.
5266 A shared context implementation will share all buffers between all rendertargets (including swapchains),
5267 implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5268 stencil buffer and incure an extra memory overhead */
5269 hr = IWineD3DDeviceImpl_ActiveRender(iface, pRenderTarget);
5272 if (SUCCEEDED(hr)) {
5273 /* Finally, reset the viewport as the MSDN states. */
5274 /* TODO: Replace impl usage */
5275 viewport.Height = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Height;
5276 viewport.Width = ((IWineD3DSurfaceImpl *)This->renderTarget)->currentDesc.Width;
5279 viewport.MaxZ = 1.0f;
5280 viewport.MinZ = 0.0f;
5281 IWineD3DDeviceImpl_SetViewport(iface, &viewport);
5283 FIXME("Unknown error setting the render target\n");
5285 This->sceneEnded = FALSE;
5289 HRESULT WINAPI IWineD3DDeviceImpl_SetDepthStencilSurface(IWineD3DDevice *iface, IWineD3DSurface *pNewZStencil) {
5290 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5291 HRESULT hr = D3D_OK;
5292 IWineD3DSurface *tmp;
5294 TRACE("(%p) Swapping z-buffer\n",This);
5296 if (pNewZStencil == This->stencilBufferTarget) {
5297 TRACE("Trying to do a NOP SetRenderTarget operation\n");
5299 /** OpenGL doesn't support 'sharing' of the stencilBuffer so we may incure an extra memory overhead
5300 * depending on the renter target implementation being used.
5301 * A shared context implementation will share all buffers between all rendertargets (including swapchains),
5302 * implementations that use separate pbuffers for different swapchains or rendertargets will have to duplicate the
5303 * stencil buffer and incure an extra memory overhead
5304 ******************************************************/
5307 tmp = This->stencilBufferTarget;
5308 This->stencilBufferTarget = pNewZStencil;
5309 /* should we be calling the parent or the wined3d surface? */
5310 if (NULL != This->stencilBufferTarget) IWineD3DSurface_AddRef(This->stencilBufferTarget);
5311 if (NULL != tmp) IWineD3DSurface_Release(tmp);
5313 /** TODO: glEnable/glDisable on depth/stencil depending on
5314 * pNewZStencil is NULL and the depth/stencil is enabled in d3d
5315 **********************************************************/
5322 /* Internal functions not in DirectX */
5323 /** TODO: move this off to the opengl context manager
5324 *(the swapchain doesn't need to know anything about offscreen rendering!)
5325 ****************************************************/
5327 HRESULT WINAPI IWineD3DDeviceImpl_CleanRender(IWineD3DDevice* iface, IWineD3DSwapChainImpl *swapchain)
5329 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5331 TRACE("(%p), %p\n", This, swapchain);
5333 if (swapchain->win != swapchain->drawable) {
5334 /* Set everything back the way it ws */
5335 swapchain->render_ctx = swapchain->glCtx;
5336 swapchain->drawable = swapchain->win;
5340 /* TODO: move this off into a context manager so that GLX_ATI_render_texture and other types of surface can be used. */
5341 HRESULT WINAPI IWineD3DDeviceImpl_FindGLContext(IWineD3DDevice *iface, IWineD3DSurface *pSurface, glContext **context) {
5342 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5345 unsigned int height;
5346 WINED3DFORMAT format;
5347 WINED3DSURFACE_DESC surfaceDesc;
5348 memset(&surfaceDesc, 0, sizeof(surfaceDesc));
5349 surfaceDesc.Width = &width;
5350 surfaceDesc.Height = &height;
5351 surfaceDesc.Format = &format;
5352 IWineD3DSurface_GetDesc(pSurface, &surfaceDesc);
5354 /* I need a get width/height function (and should do something with the format) */
5355 for (i = 0; i < CONTEXT_CACHE; ++i) {
5356 /** NOTE: the contextCache[i].pSurface == pSurface check ceates onepbuffer per surface
5357 ATI cards don't destroy pbuffers, but as soon as resource releasing callbacks are inplace
5358 the pSurface can be set to 0 allowing it to be reused from cache **/
5359 if (This->contextCache[i].Width == width && This->contextCache[i].Height == height
5360 && (pbuffer_per_surface == FALSE || This->contextCache[i].pSurface == pSurface || This->contextCache[i].pSurface == NULL)) {
5361 *context = &This->contextCache[i];
5364 if (This->contextCache[i].Width == 0) {
5365 This->contextCache[i].pSurface = pSurface;
5366 This->contextCache[i].Width = width;
5367 This->contextCache[i].Height = height;
5368 *context = &This->contextCache[i];
5372 if (i == CONTEXT_CACHE) {
5373 int minUsage = 0x7FFFFFFF; /* MAX_INT */
5374 glContext *dropContext = 0;
5375 for (i = 0; i < CONTEXT_CACHE; i++) {
5376 if (This->contextCache[i].usedcount < minUsage) {
5377 dropContext = &This->contextCache[i];
5378 minUsage = This->contextCache[i].usedcount;
5381 /* clean up the context (this doesn't work for ATI at the moment */
5383 glXDestroyContext(swapchain->display, dropContext->context);
5384 glXDestroyPbuffer(swapchain->display, dropContext->drawable);
5387 dropContext->Width = 0;
5388 dropContext->pSurface = pSurface;
5389 *context = dropContext;
5391 if (++This->contextCache[i].usedcount == 0x7FFFFFFF /* MAX_INT */ - 1 ) {
5392 for (i = 0; i < CONTEXT_CACHE; i++) {
5393 This->contextCache[i].usedcount = max(0, This->contextCache[i].usedcount - (0x7FFFFFFF /* MAX_INT */ >> 1));
5397 if (*context != NULL)
5400 return E_OUTOFMEMORY;
5403 /** FIXME: This is currently used called whenever SetRenderTarget or SetStencilBuffer are called
5404 * the functionality needs splitting up so that we don't do more than we should do.
5405 * this only seems to impact performance a little.
5406 ******************************/
5407 HRESULT WINAPI IWineD3DDeviceImpl_ActiveRender(IWineD3DDevice* iface,
5408 IWineD3DSurface *RenderSurface) {
5409 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5411 IWineD3DSurface *StencilSurface = This->stencilBufferTarget;
5412 HRESULT ret = D3DERR_INVALIDCALL;
5413 IWineD3DSurface *tmp;
5415 * Currently only active for GLX >= 1.3
5416 * for others versions we'll have to use GLXPixmaps
5418 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
5419 * as they implement GLX 1.3 but only define GLX_VERSION_1_2
5420 * so only check OpenGL version
5421 * ..........................
5422 * I don't believe that it is a problem with NVidia headers,
5423 * XFree only supports GLX1.2, nVidia (and ATI to some extent) provide 1.3 functions
5424 * in GLX 1.2, there is no mention of the correct way to tell if the extensions are provided.
5426 * Your application will report GLX version 1.2 on glXQueryVersion.
5427 * However, it is safe to call the GLX 1.3 functions as described below.
5429 #if defined(GL_VERSION_1_3)
5431 /** TODO: we only need to look up the configuration !IF! we are setting the target to a texture **/
5432 GLXFBConfig* cfgs = NULL;
5436 IWineD3DSwapChain *currentSwapchain;
5437 IWineD3DSwapChainImpl *swapchain;
5438 /** TODO: get rid of Impl usage we should always create a zbuffer/stencil with our contexts if possible,
5439 * but switch them off if the StencilSurface is set to NULL
5440 ** *********************************************************/
5441 D3DFORMAT BackBufferFormat = ((IWineD3DSurfaceImpl *) RenderSurface)->resource.format;
5442 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IWineD3DSurfaceImpl *) StencilSurface)->resource.format : 0;
5445 if StencilSurface == NULL && zBufferTarget != NULL then switch the zbuffer off,
5446 it StencilSurface != NULL && zBufferTarget == NULL switch it on
5449 #define PUSH1(att) attribs[nAttribs++] = (att);
5450 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
5452 /* PUSH2(GLX_BIND_TO_TEXTURE_RGBA_ATI, True); examples of this are few and far between (but I've got a nice working one!)*/
5454 /** TODO: remove the reff to Impl (context manager should fix this!) **/
5455 IWineD3DSwapChainImpl *impSwapChain;
5456 IWineD3DDevice_GetSwapChain(iface, 0, (IWineD3DSwapChain **)&impSwapChain);
5457 if (NULL == impSwapChain) { /* NOTE: This should NEVER fail */
5458 ERR("(%p) Failed to get a the implicit swapchain\n", iface);
5463 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
5464 PUSH2(GLX_X_RENDERABLE, TRUE);
5465 PUSH2(GLX_DOUBLEBUFFER, TRUE);
5466 TRACE("calling makeglcfg\n");
5467 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, FALSE /* alternate */);
5470 TRACE("calling chooseFGConfig\n");
5471 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5474 if (!cfgs) { /* OK we didn't find the exact config, so use any reasonable match */
5475 /* TODO: fill in the 'requested' and 'current' depths, also make sure that's
5476 why we failed and only show this message once! */
5477 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"); /**/
5479 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT | GLX_WINDOW_BIT);
5480 /* PUSH2(GLX_X_RENDERABLE, TRUE); */
5481 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
5482 PUSH2(GLX_DOUBLEBUFFER, FALSE);
5483 TRACE("calling makeglcfg\n");
5484 D3DFmtMakeGlCfg(BackBufferFormat, StencilBufferFormat, attribs, &nAttribs, TRUE /* alternate */);
5486 cfgs = glXChooseFBConfig(impSwapChain->display, DefaultScreen(impSwapChain->display),
5493 for (i = 0; i < nCfgs; ++i) {
5494 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat,
5495 debug_d3dformat(BackBufferFormat), StencilBufferFormat,
5496 debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
5499 if (NULL != This->renderTarget) {
5501 vcheckGLcall("glFlush");
5502 /** This is only useful if the old render target was a swapchain,
5503 * we need to supercede this with a function that displays
5504 * the current buffer on the screen. This is easy to do in glx1.3 but
5505 * we need to do copy-write pixels in glx 1.2.
5506 ************************************************/
5507 glXSwapBuffers(impSwapChain->display, impSwapChain->drawable);
5509 printf("Hit Enter to get next frame ...\n");
5515 if (IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)¤tSwapchain) != D3D_OK) {
5516 /* the selected render target doesn't belong to a swapchain, so use the devices implicit swapchain */
5517 IWineD3DDevice_GetSwapChain(iface, 0, ¤tSwapchain);
5521 * TODO: remove the use of IWineD3DSwapChainImpl, a context manager will help since it will replace the
5522 * renderTarget = swapchain->backBuffer bit and anything to do with *glContexts
5523 **********************************************************************/
5524 if (IWineD3DSurface_GetContainer(RenderSurface, &IID_IWineD3DSwapChain, (void **)&swapchain) == D3D_OK) {
5525 /* We also need to make sure that the lights &co are also in the context of the swapchains */
5526 /* FIXME: If the render target gets sent to the frontBuffer should be be presenting it raw? */
5527 TRACE("making swapchain active\n");
5528 if (RenderSurface != This->renderTarget) {
5529 if (RenderSurface == swapchain->backBuffer) {
5531 /* This could be flagged so that some operations work directly with the front buffer */
5532 FIXME("Attempting to set the renderTarget to the frontBuffer\n");
5534 if (glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx)
5536 TRACE("Error in setting current context: context %p drawable %ld !\n",
5537 impSwapChain->glCtx, impSwapChain->win);
5540 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5542 checkGLcall("glXMakeContextCurrent");
5544 IWineD3DSwapChain_Release((IWineD3DSwapChain *)swapchain);
5546 else if (pbuffer_support == TRUE && cfgs != NULL /* && some test to make sure that opengl supports pbuffers */) {
5548 /** ********************************************************************
5549 * This is a quickly hacked out implementation of offscreen textures.
5550 * It will work in most cases but there may be problems if the client
5551 * modifies the texture directly, or expects the contents of the rendertarget
5554 * There are some real speed vs compatibility issues here:
5555 * we should really use a new context for every texture, but that eats ram.
5556 * we should also be restoring the texture to the pbuffer but that eats CPU
5557 * we can also 'reuse' the current pbuffer if the size is larger than the requested buffer,
5558 * but if this means reusing the display backbuffer then we need to make sure that
5559 * states are correctly preserved.
5560 * In many cases I would expect that we can 'skip' some functions, such as preserving states,
5561 * and gain a good performance increase at the cost of compatibility.
5562 * I would suggest that, when this is the case, a user configurable flag be made
5563 * available, allowing the user to choose the best emmulated experience for them.
5564 *********************************************************************/
5566 XVisualInfo *visinfo;
5567 glContext *newContext;
5569 /* Here were using a shared context model */
5570 if (D3D_OK != IWineD3DDeviceImpl_FindGLContext(iface, RenderSurface, &newContext)) {
5571 FIXME("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5574 /* If the context doesn't exist then create a new one */
5575 /* TODO: This should really be part of findGlContext */
5576 if (NULL == newContext->context) {
5578 TRACE("making new buffer\n");
5580 PUSH2(GLX_PBUFFER_WIDTH, newContext->Width);
5581 PUSH2(GLX_PBUFFER_HEIGHT, newContext->Height);
5584 newContext->drawable = glXCreatePbuffer(impSwapChain->display, cfgs[0], attribs);
5586 /** ****************************************
5587 *GLX1.3 isn't supported by XFree 'yet' untill that point ATI emulates pBuffers
5589 * In future releases, we may provide the calls glXCreateNewContext,
5590 * glXQueryDrawable and glXMakeContextCurrent.
5591 * so until then we have to use glXGetVisualFromFBConfig &co..
5592 ********************************************/
5595 visinfo = glXGetVisualFromFBConfig(impSwapChain->display, cfgs[0]);
5597 ERR("Error: couldn't get an RGBA, double-buffered visual\n");
5599 newContext->context = glXCreateContext(impSwapChain->display, visinfo, impSwapChain->glCtx, GL_TRUE);
5603 if (NULL == newContext || NULL == newContext->context) {
5604 ERR("(%p) : Failed to find a context for surface %p\n", iface, RenderSurface);
5606 /* Debug logging, (this function leaks), change to a TRACE when the leak is plugged */
5607 if (glXMakeCurrent(impSwapChain->display, newContext->drawable, newContext->context) == False) {
5608 TRACE("Error in setting current context: context %p drawable %ld\n", newContext->context, newContext->drawable);
5611 /* Clean up the old context */
5612 IWineD3DDeviceImpl_CleanRender(iface, (IWineD3DSwapChainImpl *)currentSwapchain);
5613 /* Set the current context of the swapchain to the new context */
5614 impSwapChain->drawable = newContext->drawable;
5615 impSwapChain->render_ctx = newContext->context;
5619 #if 0 /* Apply the stateblock to the new context
5620 FIXME: This is a bit of a hack, each context should know it's own state,
5621 the directX current directX state should then be applied to the context */
5624 IWineD3DStateBlockImpl *oldUpdateStateBlock;
5625 oldUpdateStateBlock = This->updateStateBlock;
5626 oldRecording= This->isRecordingState;
5627 This->isRecordingState = FALSE;
5628 This->updateStateBlock = This->stateBlock;
5629 IWineD3DStateBlock_Apply((IWineD3DStateBlock *)This->stateBlock);
5631 This->isRecordingState = oldRecording;
5632 This->updateStateBlock = oldUpdateStateBlock;
5636 /* clean up the current rendertargets swapchain (if it belonged to one) */
5637 if (currentSwapchain != NULL) {
5638 IWineD3DSwapChain_Release((IWineD3DSwapChain *)currentSwapchain);
5641 /* Were done with the opengl context management, setup the rendertargets */
5643 tmp = This->renderTarget;
5644 This->renderTarget = RenderSurface;
5645 IWineD3DSurface_AddRef(This->renderTarget);
5646 IWineD3DSurface_Release(tmp);
5652 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
5653 /* Check that the container is not a swapchain member */
5655 IWineD3DSwapChain *tmpSwapChain;
5656 if (D3D_OK != IWineD3DSurface_GetContainer(This->renderTarget, &IID_IWineD3DSwapChain, (void **)&tmpSwapChain)) {
5657 This->renderUpsideDown = TRUE;
5659 This->renderUpsideDown = FALSE;
5660 IWineD3DSwapChain_Release(tmpSwapChain);
5662 /* Force updating the cull mode */
5663 TRACE("setting render state\n");
5664 IWineD3DDevice_GetRenderState(iface, WINED3DRS_CULLMODE, &value);
5665 IWineD3DDevice_SetRenderState(iface, WINED3DRS_CULLMODE, value);
5667 /* Force updating projection matrix */
5668 This->last_was_rhw = FALSE;
5669 This->proj_valid = FALSE;
5677 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat,
5678 debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
5683 if ( NULL != impSwapChain) {
5684 IWineD3DSwapChain_Release((IWineD3DSwapChain *)impSwapChain);
5692 HRESULT WINAPI IWineD3DDeviceImpl_SetCursorProperties(IWineD3DDevice* iface, UINT XHotSpot,
5693 UINT YHotSpot, IWineD3DSurface *pCursorBitmap) {
5694 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5695 /* TODO: the use of Impl is deprecated. */
5696 /* some basic validation checks */
5697 IWineD3DSurfaceImpl * pSur = (IWineD3DSurfaceImpl *) pCursorBitmap;
5699 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
5701 if (WINED3DFMT_A8R8G8B8 != pSur->resource.format) {
5702 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
5703 return D3DERR_INVALIDCALL;
5705 if (32 != pSur->currentDesc.Height || 32 != pSur->currentDesc.Width) {
5706 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
5707 return D3DERR_INVALIDCALL;
5709 /* TODO: make the cursor 'real' */
5711 This->xHotSpot = XHotSpot;
5712 This->yHotSpot = YHotSpot;
5717 void WINAPI IWineD3DDeviceImpl_SetCursorPosition(IWineD3DDevice* iface, int XScreenSpace, int YScreenSpace, DWORD Flags) {
5718 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5719 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
5721 This->xScreenSpace = XScreenSpace;
5722 This->yScreenSpace = YScreenSpace;
5728 BOOL WINAPI IWineD3DDeviceImpl_ShowCursor(IWineD3DDevice* iface, BOOL bShow) {
5729 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5730 TRACE("(%p) : visible(%d)\n", This, bShow);
5732 This->bCursorVisible = bShow;
5737 HRESULT WINAPI IWineD3DDeviceImpl_TestCooperativeLevel(IWineD3DDevice* iface) {
5738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5739 FIXME("(%p) : stub\n", This); /* No way of notifying yet! */
5744 HRESULT WINAPI IWineD3DDeviceImpl_EvictManagedResources(IWineD3DDevice* iface) {
5745 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5746 /** FIXME: Resource tracking needs to be done,
5747 * The closes we can do to this is set the priorities of all managed textures low
5748 * and then reset them.
5749 ***********************************************************/
5750 FIXME("(%p) : stub\n", This);
5754 HRESULT WINAPI IWineD3DDeviceImpl_Rest(IWineD3DDevice* iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
5755 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5756 /** FIXME: Resource trascking needs to be done.
5757 * in effect this pulls all non only default
5758 * textures out of video memory and deletes all glTextures (glDeleteTextures)
5759 * and should clear down the context and set it up according to pPresentationParameters
5760 ***********************************************************/
5761 FIXME("(%p) : stub\n", This);
5765 HRESULT WINAPI IWineD3DDeviceImpl_SetDialogBoxMode(IWineD3DDevice *iface, BOOL bEnableDialogs) {
5766 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5767 /** FIXME: always true at the moment **/
5768 if(bEnableDialogs == FALSE) {
5769 FIXME("(%p) Dialogs cannot be disabled yet\n", This);
5775 HRESULT WINAPI IWineD3DDeviceImpl_GetCreationParameters(IWineD3DDevice *iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
5776 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5778 FIXME("(%p) : stub\n", This);
5779 /* Setup some reasonable defaults */
5780 pParameters->AdapterOrdinal = 0; /* always for now */
5781 pParameters->DeviceType = D3DDEVTYPE_HAL; /* always for now */
5782 pParameters->hFocusWindow = 0;
5783 pParameters->BehaviorFlags =0;
5787 void WINAPI IWineD3DDeviceImpl_SetGammaRamp(IWineD3DDevice * iface, UINT iSwapChain, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
5788 IWineD3DSwapChain *swapchain;
5789 HRESULT hrc = D3D_OK;
5791 TRACE("Relaying to swapchain\n");
5793 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5794 IWineD3DSwapChain_SetGammaRamp(swapchain, Flags, (D3DGAMMARAMP *)pRamp);
5795 IWineD3DSwapChain_Release(swapchain);
5800 void WINAPI IWineD3DDeviceImpl_GetGammaRamp(IWineD3DDevice *iface, UINT iSwapChain, D3DGAMMARAMP* pRamp) {
5801 IWineD3DSwapChain *swapchain;
5802 HRESULT hrc = D3D_OK;
5804 TRACE("Relaying to swapchain\n");
5806 if ((hrc = IWineD3DDeviceImpl_GetSwapChain(iface, iSwapChain, &swapchain)) == D3D_OK) {
5807 hrc =IWineD3DSwapChain_GetGammaRamp(swapchain, pRamp);
5808 IWineD3DSwapChain_Release(swapchain);
5814 /** ********************************************************
5815 * Notification functions
5816 ** ********************************************************/
5817 /** This function must be called in the release of a resource when ref == 0,
5818 * the contents of resource must still be correct,
5819 * any handels to other resource held by the caller must be closed
5820 * (e.g. a texture should release all held surfaces because telling the device that it's been released.)
5821 *****************************************************/
5822 static void WINAPI IWineD3DDeviceImpl_AddResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5823 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5824 ResourceList* resourceList;
5826 TRACE("(%p) : resource %p\n", This, resource);
5828 EnterCriticalSection(&resourceStoreCriticalSection);
5830 /* add a new texture to the frot of the linked list */
5831 resourceList = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(ResourceList));
5832 resourceList->resource = resource;
5834 /* Get the old head */
5835 resourceList->next = This->resources;
5837 This->resources = resourceList;
5838 TRACE("Added resource %p with element %p pointing to %p\n", resource, resourceList, resourceList->next);
5841 LeaveCriticalSection(&resourceStoreCriticalSection);
5846 static void WINAPI IWineD3DDeviceImpl_RemoveResource(IWineD3DDevice *iface, IWineD3DResource *resource){
5847 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
5848 ResourceList* resourceList = NULL;
5849 ResourceList* previousResourceList = NULL;
5851 TRACE("(%p) : resource %p\n", This, resource);
5854 EnterCriticalSection(&resourceStoreCriticalSection);
5856 resourceList = This->resources;
5858 while (resourceList != NULL) {
5859 if(resourceList->resource == resource) break;
5860 previousResourceList = resourceList;
5861 resourceList = resourceList->next;
5864 if (resourceList == NULL) {
5865 FIXME("Attempted to remove resource %p that hasn't been stored\n", resource);
5867 LeaveCriticalSection(&resourceStoreCriticalSection);
5871 TRACE("Found resource %p with element %p pointing to %p (previous %p)\n", resourceList->resource, resourceList, resourceList->next, previousResourceList);
5873 /* make sure we don't leave a hole in the list */
5874 if (previousResourceList != NULL) {
5875 previousResourceList->next = resourceList->next;
5877 This->resources = resourceList->next;
5881 LeaveCriticalSection(&resourceStoreCriticalSection);
5887 void WINAPI IWineD3DDeviceImpl_ResourceReleased(IWineD3DDevice *iface, IWineD3DResource *resource){
5888 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5891 TRACE("(%p) : resource %p\n", This, resource);
5892 switch(IWineD3DResource_GetType(resource)){
5893 case D3DRTYPE_SURFACE:
5894 /* TODO: check front and back buffers, rendertargets etc.. possibly swapchains? */
5896 case D3DRTYPE_TEXTURE:
5897 case D3DRTYPE_CUBETEXTURE:
5898 case D3DRTYPE_VOLUMETEXTURE:
5899 for (counter = 0; counter < GL_LIMITS(textures); counter++) {
5900 if (This->stateBlock != NULL && This->stateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5901 IUnknown *textureParent;
5902 IWineD3DBaseTexture_GetParent(This->stateBlock->textures[counter], &textureParent);
5903 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5904 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5905 IUnknown_Release(textureParent);
5906 This->stateBlock->textures[counter] = NULL;
5908 if (This->updateStateBlock != This->stateBlock ){
5909 if (This->updateStateBlock->textures[counter] == (IWineD3DBaseTexture *)resource) {
5910 IUnknown *textureParent;
5911 IWineD3DBaseTexture_GetParent(This->updateStateBlock->textures[counter], &textureParent);
5912 /* TODO: Change this to a warn when we are sure our internal reference counting is ok. */
5913 FIXME("Texture being released is still by a stateblock, Stage = %u Texture = %p Parent = %p\n", counter, resource, textureParent);
5914 IUnknown_Release(textureParent);
5915 This->updateStateBlock->textures[counter] = NULL;
5920 case D3DRTYPE_VOLUME:
5921 /* TODO: nothing really? */
5923 case D3DRTYPE_VERTEXBUFFER:
5924 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed. */
5927 TRACE("Cleaning up stream pointers\n");
5929 for(streamNumber = 0; streamNumber < MAX_STREAMS; streamNumber ++){
5930 /* FINDOUT: should a warn be generated if were recording and updateStateBlock->streamSource is lost?
5931 FINDOUT: should changes.streamSource[StreamNumber] be set ?
5933 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5934 if ((IWineD3DResource *)This->updateStateBlock->streamSource[streamNumber] == resource) {
5935 FIXME("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5936 This->updateStateBlock->streamSource[streamNumber] = 0;
5937 /* Set changed flag? */
5940 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) */
5941 if ((IWineD3DResource *)This->stateBlock->streamSource[streamNumber] == resource) {
5942 TRACE("Vertex buffer released whlst bound to a state block stream %d\n", streamNumber);
5943 This->stateBlock->streamSource[streamNumber] = 0;
5946 #if 0 /* TODO: Manage internal tracking properly so that 'this shouldn't happen' */
5947 else { /* This shouldn't happen */
5948 FIXME("Calling application has released the device before relasing all the resources bound to the device\n");
5955 case D3DRTYPE_INDEXBUFFER:
5956 /* MSDN: When an application no longer holds a references to this interface, the interface will automatically be freed.*/
5957 if (This->updateStateBlock != NULL ) { /* ==NULL when device is being destroyed */
5958 if (This->updateStateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5959 This->updateStateBlock->pIndexData = NULL;
5962 if (This->stateBlock != NULL ) { /* ==NULL when device is being destroyed */
5963 if (This->stateBlock->pIndexData == (IWineD3DIndexBuffer *)resource) {
5964 This->stateBlock->pIndexData = NULL;
5970 FIXME("(%p) unknown resource type %p %u \n", This, resource, IWineD3DResource_GetType(resource));
5975 /* Remove the resoruce from the resourceStore */
5976 IWineD3DDeviceImpl_RemoveResource(iface, resource);
5978 TRACE("Resource released\n");
5983 /** This function is to be called by the swapchain when it is released and it's ref = 0
5984 *****************************************************/
5985 void WINAPI IWineD3DDeviceImpl_SwapChainReleased(IWineD3DDevice *iface, IWineD3DSwapChain *swapChain){
5986 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *) iface;
5987 SwapChainList **nextSwapchain;
5988 nextSwapchain = &This->swapchains;
5990 /* Check to see if the swapchian is being used as the render target */
5991 if (This->renderTarget != NULL) {
5992 IWineD3DSurface *swapchainBackBuffer;
5994 IWineD3DSwapChain_GetBackBuffer(swapChain, 0 ,( D3DBACKBUFFER_TYPE) 0, &swapchainBackBuffer);
5995 if (This->renderTarget == swapchainBackBuffer) {
5996 /* Don't know what to do, so warn and carry on as usual (which in this case leaves the renderterget in limbo) */
5997 FIXME("Atempting to release a swapchain that is currently beuing used as a render target, behaviour is undefined\n");
6001 /* Go through the swapchain list and try to find the swapchain being released */
6002 while(*nextSwapchain != NULL && (*nextSwapchain)->swapchain != swapChain) {
6003 nextSwapchain = &(*nextSwapchain)->next;
6006 /* Check to see if we found the swapchain */
6007 if (NULL != *nextSwapchain) {
6008 /* We found the swapchain so remove it from the list */
6009 TRACE("(%p) releasing swapchain(%p)\n", iface, swapChain);
6010 HeapFree(GetProcessHeap(), 0 , *nextSwapchain);
6011 *nextSwapchain = (*nextSwapchain)->next;
6013 /* We didn't find the swapchain on the list, this can only heppen because of a programming error in wined3d */
6014 FIXME("(%p) Attempting to release a swapchain (%p) that hasn't been stored\n", iface, swapChain);
6017 TRACE("swapchain (%p) released\n", swapChain);
6021 /**********************************************************
6022 * IWineD3DDevice VTbl follows
6023 **********************************************************/
6025 const IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
6027 /*** IUnknown methods ***/
6028 IWineD3DDeviceImpl_QueryInterface,
6029 IWineD3DDeviceImpl_AddRef,
6030 IWineD3DDeviceImpl_Release,
6031 /*** IWineD3DDevice methods ***/
6032 IWineD3DDeviceImpl_GetParent,
6033 /*** Creation methods**/
6034 IWineD3DDeviceImpl_CreateVertexBuffer,
6035 IWineD3DDeviceImpl_CreateIndexBuffer,
6036 IWineD3DDeviceImpl_CreateStateBlock,
6037 IWineD3DDeviceImpl_CreateSurface,
6038 IWineD3DDeviceImpl_CreateTexture,
6039 IWineD3DDeviceImpl_CreateVolumeTexture,
6040 IWineD3DDeviceImpl_CreateVolume,
6041 IWineD3DDeviceImpl_CreateCubeTexture,
6042 IWineD3DDeviceImpl_CreateQuery,
6043 IWineD3DDeviceImpl_CreateAdditionalSwapChain,
6044 IWineD3DDeviceImpl_CreateVertexDeclaration,
6045 IWineD3DDeviceImpl_CreateVertexShader,
6046 IWineD3DDeviceImpl_CreatePixelShader,
6048 /*** Odd functions **/
6049 IWineD3DDeviceImpl_EvictManagedResources,
6050 IWineD3DDeviceImpl_GetAvailableTextureMem,
6051 IWineD3DDeviceImpl_GetBackBuffer,
6052 IWineD3DDeviceImpl_GetCreationParameters,
6053 IWineD3DDeviceImpl_GetDeviceCaps,
6054 IWineD3DDeviceImpl_GetDirect3D,
6055 IWineD3DDeviceImpl_GetDisplayMode,
6056 IWineD3DDeviceImpl_GetNumberOfSwapChains,
6057 IWineD3DDeviceImpl_GetRasterStatus,
6058 IWineD3DDeviceImpl_GetSwapChain,
6059 IWineD3DDeviceImpl_Reset,
6060 IWineD3DDeviceImpl_SetDialogBoxMode,
6061 IWineD3DDeviceImpl_SetCursorProperties,
6062 IWineD3DDeviceImpl_SetCursorPosition,
6063 IWineD3DDeviceImpl_ShowCursor,
6064 IWineD3DDeviceImpl_TestCooperativeLevel,
6065 /*** Getters and setters **/
6066 IWineD3DDeviceImpl_SetClipPlane,
6067 IWineD3DDeviceImpl_GetClipPlane,
6068 IWineD3DDeviceImpl_SetClipStatus,
6069 IWineD3DDeviceImpl_GetClipStatus,
6070 IWineD3DDeviceImpl_SetCurrentTexturePalette,
6071 IWineD3DDeviceImpl_GetCurrentTexturePalette,
6072 IWineD3DDeviceImpl_SetDepthStencilSurface,
6073 IWineD3DDeviceImpl_GetDepthStencilSurface,
6074 IWineD3DDeviceImpl_SetFVF,
6075 IWineD3DDeviceImpl_GetFVF,
6076 IWineD3DDeviceImpl_SetGammaRamp,
6077 IWineD3DDeviceImpl_GetGammaRamp,
6078 IWineD3DDeviceImpl_SetIndices,
6079 IWineD3DDeviceImpl_GetIndices,
6080 IWineD3DDeviceImpl_SetLight,
6081 IWineD3DDeviceImpl_GetLight,
6082 IWineD3DDeviceImpl_SetLightEnable,
6083 IWineD3DDeviceImpl_GetLightEnable,
6084 IWineD3DDeviceImpl_SetMaterial,
6085 IWineD3DDeviceImpl_GetMaterial,
6086 IWineD3DDeviceImpl_SetNPatchMode,
6087 IWineD3DDeviceImpl_GetNPatchMode,
6088 IWineD3DDeviceImpl_SetPaletteEntries,
6089 IWineD3DDeviceImpl_GetPaletteEntries,
6090 IWineD3DDeviceImpl_SetPixelShader,
6091 IWineD3DDeviceImpl_GetPixelShader,
6092 IWineD3DDeviceImpl_SetPixelShaderConstantB,
6093 IWineD3DDeviceImpl_GetPixelShaderConstantB,
6094 IWineD3DDeviceImpl_SetPixelShaderConstantI,
6095 IWineD3DDeviceImpl_GetPixelShaderConstantI,
6096 IWineD3DDeviceImpl_SetPixelShaderConstantF,
6097 IWineD3DDeviceImpl_GetPixelShaderConstantF,
6098 IWineD3DDeviceImpl_SetRenderState,
6099 IWineD3DDeviceImpl_GetRenderState,
6100 IWineD3DDeviceImpl_SetRenderTarget,
6101 IWineD3DDeviceImpl_GetRenderTarget,
6102 IWineD3DDeviceImpl_SetSamplerState,
6103 IWineD3DDeviceImpl_GetSamplerState,
6104 IWineD3DDeviceImpl_SetScissorRect,
6105 IWineD3DDeviceImpl_GetScissorRect,
6106 IWineD3DDeviceImpl_SetSoftwareVertexProcessing,
6107 IWineD3DDeviceImpl_GetSoftwareVertexProcessing,
6108 IWineD3DDeviceImpl_SetStreamSource,
6109 IWineD3DDeviceImpl_GetStreamSource,
6110 IWineD3DDeviceImpl_SetStreamSourceFreq,
6111 IWineD3DDeviceImpl_GetStreamSourceFreq,
6112 IWineD3DDeviceImpl_SetTexture,
6113 IWineD3DDeviceImpl_GetTexture,
6114 IWineD3DDeviceImpl_SetTextureStageState,
6115 IWineD3DDeviceImpl_GetTextureStageState,
6116 IWineD3DDeviceImpl_SetTransform,
6117 IWineD3DDeviceImpl_GetTransform,
6118 IWineD3DDeviceImpl_SetVertexDeclaration,
6119 IWineD3DDeviceImpl_GetVertexDeclaration,
6120 IWineD3DDeviceImpl_SetVertexShader,
6121 IWineD3DDeviceImpl_GetVertexShader,
6122 IWineD3DDeviceImpl_SetVertexShaderConstantB,
6123 IWineD3DDeviceImpl_GetVertexShaderConstantB,
6124 IWineD3DDeviceImpl_SetVertexShaderConstantI,
6125 IWineD3DDeviceImpl_GetVertexShaderConstantI,
6126 IWineD3DDeviceImpl_SetVertexShaderConstantF,
6127 IWineD3DDeviceImpl_GetVertexShaderConstantF,
6128 IWineD3DDeviceImpl_SetViewport,
6129 IWineD3DDeviceImpl_GetViewport,
6130 IWineD3DDeviceImpl_MultiplyTransform,
6131 IWineD3DDeviceImpl_ValidateDevice,
6132 IWineD3DDeviceImpl_ProcessVertices,
6133 /*** State block ***/
6134 IWineD3DDeviceImpl_BeginStateBlock,
6135 IWineD3DDeviceImpl_EndStateBlock,
6136 /*** Scene management ***/
6137 IWineD3DDeviceImpl_BeginScene,
6138 IWineD3DDeviceImpl_EndScene,
6139 IWineD3DDeviceImpl_Present,
6140 IWineD3DDeviceImpl_Clear,
6142 IWineD3DDeviceImpl_DrawPrimitive,
6143 IWineD3DDeviceImpl_DrawIndexedPrimitive,
6144 IWineD3DDeviceImpl_DrawPrimitiveUP,
6145 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
6146 IWineD3DDeviceImpl_DrawRectPatch,
6147 IWineD3DDeviceImpl_DrawTriPatch,
6148 IWineD3DDeviceImpl_DeletePatch,
6149 IWineD3DDeviceImpl_ColorFill,
6150 IWineD3DDeviceImpl_UpdateTexture,
6151 IWineD3DDeviceImpl_UpdateSurface,
6152 IWineD3DDeviceImpl_StretchRect,
6153 IWineD3DDeviceImpl_GetRenderTargetData,
6154 IWineD3DDeviceImpl_GetFrontBufferData,
6155 /*** Internal use IWineD3DDevice methods ***/
6156 IWineD3DDeviceImpl_SetupTextureStates,
6157 IWineD3DDeviceImpl_SwapChainReleased,
6158 /*** object tracking ***/
6159 IWineD3DDeviceImpl_ResourceReleased
6163 const DWORD SavedPixelStates_R[NUM_SAVEDPIXELSTATES_R] = {
6164 WINED3DRS_ALPHABLENDENABLE ,
6165 WINED3DRS_ALPHAFUNC ,
6166 WINED3DRS_ALPHAREF ,
6167 WINED3DRS_ALPHATESTENABLE ,
6169 WINED3DRS_COLORWRITEENABLE ,
6170 WINED3DRS_DESTBLEND ,
6171 WINED3DRS_DITHERENABLE ,
6172 WINED3DRS_FILLMODE ,
6173 WINED3DRS_FOGDENSITY ,
6175 WINED3DRS_FOGSTART ,
6176 WINED3DRS_LASTPIXEL ,
6177 WINED3DRS_SHADEMODE ,
6178 WINED3DRS_SRCBLEND ,
6179 WINED3DRS_STENCILENABLE ,
6180 WINED3DRS_STENCILFAIL ,
6181 WINED3DRS_STENCILFUNC ,
6182 WINED3DRS_STENCILMASK ,
6183 WINED3DRS_STENCILPASS ,
6184 WINED3DRS_STENCILREF ,
6185 WINED3DRS_STENCILWRITEMASK ,
6186 WINED3DRS_STENCILZFAIL ,
6187 WINED3DRS_TEXTUREFACTOR ,
6198 WINED3DRS_ZWRITEENABLE
6201 const DWORD SavedPixelStates_T[NUM_SAVEDPIXELSTATES_T] = {
6202 WINED3DTSS_ADDRESSW ,
6203 WINED3DTSS_ALPHAARG0 ,
6204 WINED3DTSS_ALPHAARG1 ,
6205 WINED3DTSS_ALPHAARG2 ,
6206 WINED3DTSS_ALPHAOP ,
6207 WINED3DTSS_BUMPENVLOFFSET ,
6208 WINED3DTSS_BUMPENVLSCALE ,
6209 WINED3DTSS_BUMPENVMAT00 ,
6210 WINED3DTSS_BUMPENVMAT01 ,
6211 WINED3DTSS_BUMPENVMAT10 ,
6212 WINED3DTSS_BUMPENVMAT11 ,
6213 WINED3DTSS_COLORARG0 ,
6214 WINED3DTSS_COLORARG1 ,
6215 WINED3DTSS_COLORARG2 ,
6216 WINED3DTSS_COLOROP ,
6217 WINED3DTSS_RESULTARG ,
6218 WINED3DTSS_TEXCOORDINDEX ,
6219 WINED3DTSS_TEXTURETRANSFORMFLAGS
6222 const DWORD SavedPixelStates_S[NUM_SAVEDPIXELSTATES_S] = {
6223 WINED3DSAMP_ADDRESSU ,
6224 WINED3DSAMP_ADDRESSV ,
6225 WINED3DSAMP_ADDRESSW ,
6226 WINED3DSAMP_BORDERCOLOR ,
6227 WINED3DSAMP_MAGFILTER ,
6228 WINED3DSAMP_MINFILTER ,
6229 WINED3DSAMP_MIPFILTER ,
6230 WINED3DSAMP_MIPMAPLODBIAS ,
6231 WINED3DSAMP_MAXMIPLEVEL ,
6232 WINED3DSAMP_MAXANISOTROPY ,
6233 WINED3DSAMP_SRGBTEXTURE ,
6234 WINED3DSAMP_ELEMENTINDEX
6237 const DWORD SavedVertexStates_R[NUM_SAVEDVERTEXSTATES_R] = {
6239 WINED3DRS_AMBIENTMATERIALSOURCE ,
6240 WINED3DRS_CLIPPING ,
6241 WINED3DRS_CLIPPLANEENABLE ,
6242 WINED3DRS_COLORVERTEX ,
6243 WINED3DRS_DIFFUSEMATERIALSOURCE ,
6244 WINED3DRS_EMISSIVEMATERIALSOURCE ,
6245 WINED3DRS_FOGDENSITY ,
6247 WINED3DRS_FOGSTART ,
6248 WINED3DRS_FOGTABLEMODE ,
6249 WINED3DRS_FOGVERTEXMODE ,
6250 WINED3DRS_INDEXEDVERTEXBLENDENABLE ,
6251 WINED3DRS_LIGHTING ,
6252 WINED3DRS_LOCALVIEWER ,
6253 WINED3DRS_MULTISAMPLEANTIALIAS ,
6254 WINED3DRS_MULTISAMPLEMASK ,
6255 WINED3DRS_NORMALIZENORMALS ,
6256 WINED3DRS_PATCHEDGESTYLE ,
6257 WINED3DRS_POINTSCALE_A ,
6258 WINED3DRS_POINTSCALE_B ,
6259 WINED3DRS_POINTSCALE_C ,
6260 WINED3DRS_POINTSCALEENABLE ,
6261 WINED3DRS_POINTSIZE ,
6262 WINED3DRS_POINTSIZE_MAX ,
6263 WINED3DRS_POINTSIZE_MIN ,
6264 WINED3DRS_POINTSPRITEENABLE ,
6265 WINED3DRS_RANGEFOGENABLE ,
6266 WINED3DRS_SPECULARMATERIALSOURCE ,
6267 WINED3DRS_TWEENFACTOR ,
6268 WINED3DRS_VERTEXBLEND
6271 const DWORD SavedVertexStates_T[NUM_SAVEDVERTEXSTATES_T] = {
6272 WINED3DTSS_TEXCOORDINDEX ,
6273 WINED3DTSS_TEXTURETRANSFORMFLAGS
6276 const DWORD SavedVertexStates_S[NUM_SAVEDVERTEXSTATES_S] = {
6277 WINED3DSAMP_DMAPOFFSET