2 * IWineD3DDevice implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "wined3d_private.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
27 WINE_DECLARE_DEBUG_CHANNEL(d3d_caps);
28 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
29 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
31 /**********************************************************
32 * Global variable / Constants follow
33 **********************************************************/
34 const float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; /* When needed for comparisons */
36 /**********************************************************
37 * Utility functions follow
38 **********************************************************/
39 /* Convert the D3DLIGHT properties into equivalent gl lights */
40 void setup_light(IWineD3DDevice *iface, LONG Index, PLIGHTINFOEL *lightInfo) {
43 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
44 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
46 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
47 glMatrixMode(GL_MODELVIEW);
49 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
52 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
53 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
54 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
55 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
56 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
57 checkGLcall("glLightfv");
60 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
61 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
62 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
63 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
64 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
65 checkGLcall("glLightfv");
68 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
69 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
70 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
71 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
72 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
73 checkGLcall("glLightfv");
75 /* Attenuation - Are these right? guessing... */
76 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
77 checkGLcall("glLightf");
78 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
79 checkGLcall("glLightf");
81 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
82 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
83 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
84 checkGLcall("glLightf");
86 switch (lightInfo->OriginalParms.Type) {
89 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
90 checkGLcall("glLightfv");
91 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
92 checkGLcall("glLightf");
98 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
99 checkGLcall("glLightfv");
101 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
102 checkGLcall("glLightfv");
103 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
104 checkGLcall("glLightf");
105 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
106 checkGLcall("glLightf");
110 case D3DLIGHT_DIRECTIONAL:
112 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
113 checkGLcall("glLightfv");
114 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
115 checkGLcall("glLightf");
116 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
117 checkGLcall("glLightf");
121 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
124 /* Restore the modelview matrix */
128 /* Apply the current values to the specified texture stage */
129 void WINAPI IWineD3DDeviceImpl_SetupTextureStates(IWineD3DDevice *iface, DWORD Stage, DWORD Flags) {
130 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
133 BOOL changeTexture = TRUE;
135 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
136 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
141 /* Performance: For texture states where multiples effect the outcome, only bother
142 applying the last one as it will pick up all the other values */
143 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
144 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
145 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
146 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
147 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
148 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
152 /* Performance: If the texture states only impact settings for the texture unit
153 (compared to the texture object) then there is no need to reapply them. The
154 only time they need applying is the first time, since we cheat and put the
155 values into the stateblock without applying.
156 Per-texture unit: texture function (eg. combine), ops and args
158 texture generation settings
159 Note: Due to some special conditions there may be a need to do particular ones
160 of these, which is what the Flags allows */
162 case D3DTSS_TEXCOORDINDEX:
163 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
167 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
175 /* Performance: Only change to this texture if we have to */
177 /* Make appropriate texture active */
178 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
179 GLACTIVETEXTURE(Stage);
180 } else if (Stage > 0) {
181 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
183 changeTexture = FALSE;
186 /* Now apply the change */
187 IWineD3DDevice_SetTextureStageState(iface, Stage, i, This->stateBlock->textureState[Stage][i]);
191 /* Note the D3DRS value applies to all textures, but GL has one
192 * per texture, so apply it now ready to be used!
194 D3DCOLORTOGLFLOAT4(This->stateBlock->renderState[D3DRS_TEXTUREFACTOR], col);
195 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
196 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
198 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
201 /**********************************************************
202 * IWineD3DDevice implementation follows
203 **********************************************************/
204 HRESULT WINAPI IWineD3DDeviceImpl_GetParent(IWineD3DDevice *iface, IUnknown **pParent) {
205 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
206 *pParent = This->parent;
207 IUnknown_AddRef(This->parent);
212 * Creation of other classes
214 HRESULT WINAPI IWineD3DDeviceImpl_CreateVertexBuffer(IWineD3DDevice *iface, UINT Size, DWORD Usage,
215 DWORD FVF, D3DPOOL Pool, IWineD3DVertexBuffer** ppVertexBuffer, HANDLE *sharedHandle,
218 IWineD3DVertexBufferImpl *object;
219 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
221 /* Allocate the storage for the device */
222 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DVertexBufferImpl));
223 if (NULL == object) {
224 *ppVertexBuffer = NULL;
225 return D3DERR_OUTOFVIDEOMEMORY;
227 object->lpVtbl = &IWineD3DVertexBuffer_Vtbl;
228 object->resource.wineD3DDevice= This;
229 IWineD3DDevice_AddRef(iface);
230 object->resource.parent = parent;
231 object->resource.resourceType = D3DRTYPE_VERTEXBUFFER;
232 object->resource.ref = 1;
233 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
234 object->currentDesc.Usage = Usage;
235 object->currentDesc.Pool = Pool;
236 object->currentDesc.FVF = FVF;
237 object->currentDesc.Size = Size;
239 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
240 *ppVertexBuffer = (IWineD3DVertexBuffer *)object;
245 HRESULT WINAPI IWineD3DDeviceImpl_CreateIndexBuffer(IWineD3DDevice *iface, UINT Length, DWORD Usage,
246 D3DFORMAT Format, D3DPOOL Pool, IWineD3DIndexBuffer** ppIndexBuffer,
247 HANDLE *sharedHandle, IUnknown *parent) {
248 IWineD3DIndexBufferImpl *object;
249 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
251 /* Allocate the storage for the device */
252 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DIndexBufferImpl));
253 if (NULL == object) {
254 *ppIndexBuffer = NULL;
255 return D3DERR_OUTOFVIDEOMEMORY;
257 object->lpVtbl = &IWineD3DIndexBuffer_Vtbl;
258 object->resource.wineD3DDevice = This;
259 IWineD3DDevice_AddRef(iface);
260 object->resource.resourceType = D3DRTYPE_INDEXBUFFER;
261 object->resource.parent = parent;
262 object->resource.ref = 1;
263 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
264 object->currentDesc.Usage = Usage;
265 object->currentDesc.Pool = Pool;
266 object->currentDesc.Format= Format;
267 object->currentDesc.Size = Length;
269 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d - Memory@%p, Iface@%p\n", This, Length, Usage, Format,
270 debug_d3dformat(Format), Pool, object, object->allocatedMemory);
271 *ppIndexBuffer = (IWineD3DIndexBuffer *) object;
276 HRESULT WINAPI IWineD3DDeviceImpl_CreateStateBlock(IWineD3DDevice* iface, D3DSTATEBLOCKTYPE Type, IWineD3DStateBlock** ppStateBlock, IUnknown *parent) {
278 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
279 IWineD3DStateBlockImpl *object;
281 /* Allocate Storage for the state block */
282 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DStateBlockImpl));
283 if (NULL == object) {
284 *ppStateBlock = NULL;
285 return D3DERR_OUTOFVIDEOMEMORY;
287 object->lpVtbl = &IWineD3DStateBlock_Vtbl;
288 object->wineD3DDevice = This;
289 IWineD3DDevice_AddRef(iface);
290 object->parent = parent;
292 object->blockType = Type;
293 *ppStateBlock = (IWineD3DStateBlock *)object;
295 /* Special case - Used during initialization to produce a placeholder stateblock
296 so other functions called can update a state block */
297 if (Type == (D3DSTATEBLOCKTYPE) 0) {
298 /* Don't bother increasing the reference count otherwise a device will never
299 be freed due to circular dependencies */
303 /* Otherwise, might as well set the whole state block to the appropriate values */
304 IWineD3DDevice_AddRef(iface);
305 memcpy(object, This->stateBlock, sizeof(IWineD3DStateBlockImpl));
306 FIXME("unfinished - needs to set up changed and set attributes\n");
310 HRESULT WINAPI IWineD3DDeviceImpl_CreateRenderTarget(IWineD3DDevice *iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample,
311 DWORD MultisampleQuality, BOOL Lockable, IWineD3DSurface** ppSurface, HANDLE* pSharedHandle,
313 IWineD3DSurfaceImpl *object;
314 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
316 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurfaceImpl));
317 if (NULL == object) {
319 return D3DERR_OUTOFVIDEOMEMORY;
321 object->lpVtbl = &IWineD3DSurface_Vtbl;
322 object->resource.wineD3DDevice = This;
323 IWineD3DDevice_AddRef(iface);
324 object->resource.resourceType = D3DRTYPE_SURFACE;
325 object->resource.parent = parent;
326 object->resource.ref = 1;
327 *ppSurface = (IWineD3DSurface *)object;
328 object->container = (IUnknown*) This;
330 object->currentDesc.Width = Width;
331 object->currentDesc.Height = Height;
332 object->currentDesc.Format = Format;
333 object->currentDesc.Type = D3DRTYPE_SURFACE;
334 object->currentDesc.Usage = D3DUSAGE_RENDERTARGET;
335 object->currentDesc.Pool = D3DPOOL_DEFAULT;
336 object->currentDesc.MultiSampleType = MultiSample;
337 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
338 if (Format == D3DFMT_DXT1) {
339 object->currentDesc_size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
341 object->currentDesc_size = (Width * object->bytesPerPixel) * Height;
343 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->currentDesc_size);
344 object->lockable = Lockable;
345 object->locked = FALSE;
346 memset(&object->lockedRect, 0, sizeof(RECT));
347 IWineD3DSurface_CleanDirtyRect(*ppSurface);
349 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) lockable(%d) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), Lockable, *ppSurface, object->allocatedMemory, object->currentDesc_size);
353 HRESULT WINAPI IWineD3DDeviceImpl_CreateOffscreenPlainSurface(IWineD3DDevice *iface,
354 UINT Width, UINT Height,
355 D3DFORMAT Format, D3DPOOL Pool,
356 IWineD3DSurface** ppSurface,
357 HANDLE* pSharedHandle, IUnknown *parent) {
359 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
360 IWineD3DSurfaceImpl *object;
362 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DSurfaceImpl));
363 if (NULL == object) {
365 return D3DERR_OUTOFVIDEOMEMORY;
368 object->lpVtbl = &IWineD3DSurface_Vtbl;
369 object->resource.wineD3DDevice = This;
370 IWineD3DDevice_AddRef(iface);
371 object->resource.resourceType = D3DRTYPE_VOLUME;
372 object->resource.parent = parent;
373 object->resource.ref = 1;
374 *ppSurface = (IWineD3DSurface *)object;
375 object->container = (IUnknown*) This;
377 TRACE("(%p) : W(%d) H(%d), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
378 Format, debug_d3dformat(Format), debug_d3dpool(Pool));
380 object->currentDesc.Width = Width;
381 object->currentDesc.Height = Height;
382 object->currentDesc.Format = Format;
383 object->currentDesc.Type = D3DRTYPE_SURFACE;
384 object->currentDesc.Usage = 0;
385 object->currentDesc.Pool = Pool;
386 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
388 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
389 it is based around 4x4 pixel blocks it requires padding, so allocate enough
391 if (Format == D3DFMT_DXT1) {
392 object->currentDesc_size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
393 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
394 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
395 object->currentDesc_size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
397 object->currentDesc_size = (Width * object->bytesPerPixel) * Height;
399 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->currentDesc_size);
400 object->lockable = TRUE;
401 object->locked = FALSE;
402 object->Dirty = FALSE;
403 TRACE("(%p) : w(%d) h(%d) fmt(%d,%s) surf@%p, surfmem@%p, %d bytes\n", This, Width, Height, Format, debug_d3dformat(Format), *ppSurface, object->allocatedMemory, object->currentDesc_size);
405 memset(&object->lockedRect, 0, sizeof(RECT));
406 return IWineD3DSurface_CleanDirtyRect(*ppSurface);
409 HRESULT WINAPI IWineD3DDeviceImpl_CreateTexture(IWineD3DDevice *iface, UINT Width,
410 UINT Height, UINT Levels, DWORD Usage,
411 D3DFORMAT Format, D3DPOOL Pool,
412 IWineD3DTexture** ppTexture,
413 HANDLE* pSharedHandle, IUnknown *parent,
414 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
416 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
417 IWineD3DTextureImpl *object;
422 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DTextureImpl));
423 if (NULL == object) {
425 return D3DERR_OUTOFVIDEOMEMORY;
428 object->lpVtbl = &IWineD3DTexture_Vtbl;
429 object->resource.wineD3DDevice = This;
430 IWineD3DDevice_AddRef(iface);
431 object->resource.resourceType = D3DRTYPE_TEXTURE;
432 object->resource.parent = parent;
433 object->resource.ref = 1;
434 *ppTexture = (IWineD3DTexture *)object;
436 TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This,
437 Width, Height, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
438 object->width = Width;
439 object->height = Height;
440 object->usage = Usage;
441 object->baseTexture.levels = Levels;
442 object->baseTexture.format = Format;
444 /* Calculate levels for mip mapping */
446 object->baseTexture.levels++;
449 while (tmpW > 1 && tmpH > 1) {
450 tmpW = max(1, tmpW / 2);
451 tmpH = max(1, tmpH / 2);
452 object->baseTexture.levels++;
454 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
457 /* Generate all the surfaces */
460 for (i = 0; i < object->baseTexture.levels; i++)
462 D3DCB_CreateSurface(This->parent, tmpW, tmpH, Format, Pool,
463 (IWineD3DSurface **)&object->surfaces[i], pSharedHandle);
464 object->surfaces[i]->container = (IUnknown*) object;
465 object->surfaces[i]->currentDesc.Usage = Usage;
466 object->surfaces[i]->currentDesc.Pool = Pool;
469 * As written in msdn in IDirect3DTexture8::LockRect
470 * Textures created in D3DPOOL_DEFAULT are not lockable.
472 if (D3DPOOL_DEFAULT == Pool) {
473 object->surfaces[i]->lockable = FALSE;
476 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
477 tmpW = max(1, tmpW / 2);
478 tmpH = max(1, tmpH / 2);
481 *ppTexture = (IWineD3DTexture *) object;
482 TRACE("(%p) : Created texture %p\n", This, object);
486 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolumeTexture(IWineD3DDevice *iface,
487 UINT Width, UINT Height, UINT Depth,
488 UINT Levels, DWORD Usage,
489 D3DFORMAT Format, D3DPOOL Pool,
490 IWineD3DVolumeTexture** ppVolumeTexture,
491 HANDLE* pSharedHandle, IUnknown *parent,
492 D3DCB_CREATEVOLUMEFN D3DCB_CreateVolume) {
494 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
495 IWineD3DVolumeTextureImpl *object;
501 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DVolumeTextureImpl));
502 if (NULL == object) {
503 *ppVolumeTexture = NULL;
504 return D3DERR_OUTOFVIDEOMEMORY;
507 object->lpVtbl = &IWineD3DVolumeTexture_Vtbl;
508 object->resource.wineD3DDevice = This;
509 IWineD3DDevice_AddRef(iface);
510 object->resource.resourceType = D3DRTYPE_VOLUMETEXTURE;
511 object->resource.parent = parent;
512 object->resource.ref = 1;
513 *ppVolumeTexture = (IWineD3DVolumeTexture *)object;
515 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
516 Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
518 object->width = Width;
519 object->height = Height;
520 object->depth = Depth;
521 object->usage = Usage;
522 object->baseTexture.levels = Levels;
523 object->baseTexture.format = Format;
525 /* Calculate levels for mip mapping */
527 object->baseTexture.levels++;
531 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
532 tmpW = max(1, tmpW / 2);
533 tmpH = max(1, tmpH / 2);
534 tmpD = max(1, tmpD / 2);
535 object->baseTexture.levels++;
537 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
540 /* Generate all the surfaces */
545 for (i = 0; i < object->baseTexture.levels; i++)
547 /* Create the volume - No entry point for this seperately?? */
548 D3DCB_CreateVolume(This->parent, Width, Height, Depth, Format, Pool, Usage,
549 (IWineD3DVolume **)&object->volumes[i], pSharedHandle);
550 object->volumes[i]->container = (IUnknown*) object;
552 tmpW = max(1, tmpW / 2);
553 tmpH = max(1, tmpH / 2);
554 tmpD = max(1, tmpD / 2);
557 *ppVolumeTexture = (IWineD3DVolumeTexture *) object;
558 TRACE("(%p) : Created volume texture %p\n", This, object);
562 HRESULT WINAPI IWineD3DDeviceImpl_CreateVolume(IWineD3DDevice *iface,
563 UINT Width, UINT Height, UINT Depth,
565 D3DFORMAT Format, D3DPOOL Pool,
566 IWineD3DVolume** ppVolume,
567 HANDLE* pSharedHandle, IUnknown *parent) {
569 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
570 IWineD3DVolumeImpl *object;
572 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DVolumeImpl));
573 if (NULL == object) {
575 return D3DERR_OUTOFVIDEOMEMORY;
578 object->lpVtbl = &IWineD3DVolume_Vtbl;
579 object->wineD3DDevice = This;
580 IWineD3DDevice_AddRef(iface);
581 object->resourceType = D3DRTYPE_VOLUME;
582 object->parent = parent;
584 *ppVolume = (IWineD3DVolume *)object;
586 TRACE("(%p) : W(%d) H(%d) D(%d), Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height,
587 Depth, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
589 object->currentDesc.Width = Width;
590 object->currentDesc.Height = Height;
591 object->currentDesc.Depth = Depth;
592 object->currentDesc.Format = Format;
593 object->currentDesc.Type = D3DRTYPE_VOLUME;
594 object->currentDesc.Pool = Pool;
595 object->currentDesc.Usage = Usage;
596 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
598 /* Note: Volume textures cannot be dxtn, hence no need to check here */
599 object->currentDesc.Size = (Width * object->bytesPerPixel) * Height * Depth;
600 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->currentDesc.Size);
601 object->lockable = TRUE;
602 object->locked = FALSE;
603 memset(&object->lockedBox, 0, sizeof(D3DBOX));
604 object->dirty = FALSE;
605 return IWineD3DVolume_CleanDirtyBox((IWineD3DVolume *) object);
608 HRESULT WINAPI IWineD3DDeviceImpl_CreateCubeTexture(IWineD3DDevice *iface, UINT EdgeLength,
609 UINT Levels, DWORD Usage,
610 D3DFORMAT Format, D3DPOOL Pool,
611 IWineD3DCubeTexture** ppCubeTexture,
612 HANDLE* pSharedHandle, IUnknown *parent,
613 D3DCB_CREATESURFACEFN D3DCB_CreateSurface) {
615 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
616 IWineD3DCubeTextureImpl *object;
620 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IWineD3DCubeTextureImpl));
621 if (NULL == object) {
622 FIXME("Allocation of memory failed\n");
623 *ppCubeTexture = NULL;
624 return D3DERR_OUTOFVIDEOMEMORY;
627 object->lpVtbl = &IWineD3DCubeTexture_Vtbl;
628 object->resource.wineD3DDevice = This;
629 IWineD3DDevice_AddRef(iface);
630 object->resource.resourceType = D3DRTYPE_CUBETEXTURE;
631 object->resource.parent = parent;
632 object->resource.ref = 1;
633 *ppCubeTexture = (IWineD3DCubeTexture *)object;
635 /* Allocate the storage for it */
636 TRACE("(%p) : Len(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, EdgeLength, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
638 object->usage = Usage;
639 object->edgeLength = EdgeLength;
640 object->baseTexture.levels = Levels;
641 object->baseTexture.format = Format;
643 /* Calculate levels for mip mapping */
645 object->baseTexture.levels++;
648 tmpW = max(1, tmpW / 2);
649 object->baseTexture.levels++;
651 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
654 /* Generate all the surfaces */
656 for (i = 0; i < object->baseTexture.levels; i++) {
658 /* Create the 6 faces */
659 for (j = 0; j < 6; j++) {
661 D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Pool,
662 (IWineD3DSurface **)&object->surfaces[j][i], pSharedHandle);
663 object->surfaces[j][i]->container = (IUnknown*) object;
664 object->surfaces[j][i]->currentDesc.Usage = Usage;
665 object->surfaces[j][i]->currentDesc.Pool = Pool;
668 * As written in msdn in IDirect3DCubeTexture8::LockRect
669 * Textures created in D3DPOOL_DEFAULT are not lockable.
671 if (D3DPOOL_DEFAULT == Pool) {
672 object->surfaces[j][i]->lockable = FALSE;
675 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
677 tmpW = max(1, tmpW / 2);
680 TRACE("(%p) : Created Cube Texture %p\n", This, object);
681 *ppCubeTexture = (IWineD3DCubeTexture *) object;
688 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
689 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
691 /* Update the current statte block */
692 This->updateStateBlock->fvf = fvf;
693 This->updateStateBlock->changed.fvf = TRUE;
694 This->updateStateBlock->set.fvf = TRUE;
696 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
698 /* No difference if recording or not */
701 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
702 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
703 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
704 *pfvf = This->stateBlock->fvf;
709 * Get / Set Stream Source
711 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
712 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
713 IWineD3DVertexBuffer *oldSrc;
715 oldSrc = This->stateBlock->stream_source[StreamNumber];
716 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
718 This->updateStateBlock->changed.stream_source[StreamNumber] = TRUE;
719 This->updateStateBlock->set.stream_source[StreamNumber] = TRUE;
720 This->updateStateBlock->stream_stride[StreamNumber] = Stride;
721 This->updateStateBlock->stream_source[StreamNumber] = pStreamData;
722 This->updateStateBlock->stream_offset[StreamNumber] = OffsetInBytes;
724 /* Handle recording of state blocks */
725 if (This->isRecordingState) {
726 TRACE("Recording... not performing anything\n");
730 /* Not recording... */
731 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
732 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
737 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
738 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
740 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->stream_source[StreamNumber], This->stateBlock->stream_stride[StreamNumber]);
741 *pStream = This->stateBlock->stream_source[StreamNumber];
742 *pStride = This->stateBlock->stream_stride[StreamNumber];
743 *pOffset = This->stateBlock->stream_offset[StreamNumber];
744 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
749 * Get / Set & Multipy Transform
751 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
752 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
754 /* Most of this routine, comments included copied from ddraw tree initially: */
755 TRACE("(%p) : Transform State=%d\n", This, d3dts);
757 /* Handle recording of state blocks */
758 if (This->isRecordingState) {
759 TRACE("Recording... not performing anything\n");
760 This->updateStateBlock->changed.transform[d3dts] = TRUE;
761 This->updateStateBlock->set.transform[d3dts] = TRUE;
762 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
767 * If the new matrix is the same as the current one,
768 * we cut off any further processing. this seems to be a reasonable
769 * optimization because as was noticed, some apps (warcraft3 for example)
770 * tend towards setting the same matrix repeatedly for some reason.
772 * From here on we assume that the new matrix is different, wherever it matters.
774 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
775 TRACE("The app is setting the same matrix over again\n");
778 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
782 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
783 where ViewMat = Camera space, WorldMat = world space.
785 In OpenGL, camera and world space is combined into GL_MODELVIEW
786 matrix. The Projection matrix stay projection matrix.
789 /* Capture the times we can just ignore the change for now */
790 if (d3dts == D3DTS_WORLDMATRIX(0)) {
791 This->modelview_valid = FALSE;
794 } else if (d3dts == D3DTS_PROJECTION) {
795 This->proj_valid = FALSE;
798 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
799 /* Indexed Vertex Blending Matrices 256 -> 511 */
800 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
801 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
805 /* Now we really are going to have to change a matrix */
808 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
809 if (d3dts < GL_LIMITS(textures)) {
810 int tex = d3dts - D3DTS_TEXTURE0;
811 GLACTIVETEXTURE(tex);
812 set_texture_matrix((float *)lpmatrix,
813 This->updateStateBlock->textureState[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
816 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
819 /* If we are changing the View matrix, reset the light and clipping planes to the new view
820 * NOTE: We have to reset the positions even if the light/plane is not currently
821 * enabled, since the call to enable it will not reset the position.
822 * NOTE2: Apparently texture transforms do NOT need reapplying
825 PLIGHTINFOEL *lightChain = NULL;
826 This->modelview_valid = FALSE;
827 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
829 glMatrixMode(GL_MODELVIEW);
830 checkGLcall("glMatrixMode(GL_MODELVIEW)");
832 glLoadMatrixf((float *)lpmatrix);
833 checkGLcall("glLoadMatrixf(...)");
836 lightChain = This->stateBlock->lights;
837 while (lightChain && lightChain->glIndex != -1) {
838 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
839 checkGLcall("glLightfv posn");
840 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
841 checkGLcall("glLightfv dirn");
842 lightChain = lightChain->next;
845 /* Reset Clipping Planes if clipping is enabled */
846 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
847 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
848 checkGLcall("glClipPlane");
852 } else { /* What was requested!?? */
853 WARN("invalid matrix specified: %i\n", d3dts);
856 /* Release lock, all done */
861 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
862 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
863 TRACE("(%p) : for Transform State %d\n", This, State);
864 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
868 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
869 D3DMATRIX *mat = NULL;
872 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
873 * below means it will be recorded in a state block change, but it
874 * works regardless where it is recorded.
875 * If this is found to be wrong, change to StateBlock.
877 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
878 TRACE("(%p) : For state %u\n", This, State);
880 if (State < HIGHEST_TRANSFORMSTATE)
882 mat = &This->updateStateBlock->transforms[State];
884 FIXME("Unhandled transform state!!\n");
887 /* Copied from ddraw code: */
888 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);
889 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);
890 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);
891 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);
893 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);
894 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);
895 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);
896 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);
898 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);
899 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);
900 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);
901 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);
903 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);
904 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);
905 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);
906 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);
908 /* Apply change via set transform - will reapply to eg. lights this way */
909 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
915 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
917 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
918 you can reference any indexes you want as long as that number max are enabled at any
919 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
920 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
921 but when recording, just build a chain pretty much of commands to be replayed. */
923 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
925 PLIGHTINFOEL *object, *temp;
927 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
928 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
930 /* If recording state block, just add to end of lights chain */
931 if (This->isRecordingState) {
932 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
933 if (NULL == object) {
934 return D3DERR_OUTOFVIDEOMEMORY;
936 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
937 object->OriginalIndex = Index;
938 object->glIndex = -1;
939 object->changed = TRUE;
941 /* Add to the END of the chain of lights changes to be replayed */
942 if (This->updateStateBlock->lights == NULL) {
943 This->updateStateBlock->lights = object;
945 temp = This->updateStateBlock->lights;
946 while (temp->next != NULL) temp=temp->next;
949 TRACE("Recording... not performing anything more\n");
953 /* Ok, not recording any longer so do real work */
954 object = This->stateBlock->lights;
955 while (object != NULL && object->OriginalIndex != Index) object = object->next;
957 /* If we didn't find it in the list of lights, time to add it */
958 if (object == NULL) {
959 PLIGHTINFOEL *insertAt,*prevPos;
961 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
962 if (NULL == object) {
963 return D3DERR_OUTOFVIDEOMEMORY;
965 object->OriginalIndex = Index;
966 object->glIndex = -1;
968 /* Add it to the front of list with the idea that lights will be changed as needed
969 BUT after any lights currently assigned GL indexes */
970 insertAt = This->stateBlock->lights;
972 while (insertAt != NULL && insertAt->glIndex != -1) {
974 insertAt = insertAt->next;
977 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
978 This->stateBlock->lights = object;
979 } else if (insertAt == NULL) { /* End of list */
980 prevPos->next = object;
981 object->prev = prevPos;
982 } else { /* Middle of chain */
983 if (prevPos == NULL) {
984 This->stateBlock->lights = object;
986 prevPos->next = object;
988 object->prev = prevPos;
989 object->next = insertAt;
990 insertAt->prev = object;
994 /* Initialze the object */
995 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,
996 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
997 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
998 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
999 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1000 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1001 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1003 /* Save away the information */
1004 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1006 switch (pLight->Type) {
1007 case D3DLIGHT_POINT:
1009 object->lightPosn[0] = pLight->Position.x;
1010 object->lightPosn[1] = pLight->Position.y;
1011 object->lightPosn[2] = pLight->Position.z;
1012 object->lightPosn[3] = 1.0f;
1013 object->cutoff = 180.0f;
1017 case D3DLIGHT_DIRECTIONAL:
1019 object->lightPosn[0] = -pLight->Direction.x;
1020 object->lightPosn[1] = -pLight->Direction.y;
1021 object->lightPosn[2] = -pLight->Direction.z;
1022 object->lightPosn[3] = 0.0;
1023 object->exponent = 0.0f;
1024 object->cutoff = 180.0f;
1029 object->lightPosn[0] = pLight->Position.x;
1030 object->lightPosn[1] = pLight->Position.y;
1031 object->lightPosn[2] = pLight->Position.z;
1032 object->lightPosn[3] = 1.0;
1035 object->lightDirn[0] = pLight->Direction.x;
1036 object->lightDirn[1] = pLight->Direction.y;
1037 object->lightDirn[2] = pLight->Direction.z;
1038 object->lightDirn[3] = 1.0;
1041 * opengl-ish and d3d-ish spot lights use too different models for the
1042 * light "intensity" as a function of the angle towards the main light direction,
1043 * so we only can approximate very roughly.
1044 * however spot lights are rather rarely used in games (if ever used at all).
1045 * furthermore if still used, probably nobody pays attention to such details.
1047 if (pLight->Falloff == 0) {
1050 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1052 if (rho < 0.0001) rho = 0.0001f;
1053 object->exponent = -0.3/log(cos(rho/2));
1054 object->cutoff = pLight->Phi*90/M_PI;
1060 FIXME("Unrecognized light type %d\n", pLight->Type);
1063 /* Update the live definitions if the light is currently assigned a glIndex */
1064 if (object->glIndex != -1) {
1065 setup_light(iface, object->glIndex, object);
1070 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1071 PLIGHTINFOEL *lightInfo = NULL;
1072 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1073 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1075 /* Locate the light in the live lights */
1076 lightInfo = This->stateBlock->lights;
1077 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1079 if (lightInfo == NULL) {
1080 TRACE("Light information requested but light not defined\n");
1081 return D3DERR_INVALIDCALL;
1084 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1089 * Get / Set Light Enable
1090 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1092 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1093 PLIGHTINFOEL *lightInfo = NULL;
1094 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1095 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1097 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1098 if (This->isRecordingState) {
1099 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1100 if (NULL == lightInfo) {
1101 return D3DERR_OUTOFVIDEOMEMORY;
1103 lightInfo->OriginalIndex = Index;
1104 lightInfo->glIndex = -1;
1105 lightInfo->enabledChanged = TRUE;
1107 /* Add to the END of the chain of lights changes to be replayed */
1108 if (This->updateStateBlock->lights == NULL) {
1109 This->updateStateBlock->lights = lightInfo;
1111 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1112 while (temp->next != NULL) temp=temp->next;
1113 temp->next = lightInfo;
1115 TRACE("Recording... not performing anything more\n");
1119 /* Not recording... So, locate the light in the live lights */
1120 lightInfo = This->stateBlock->lights;
1121 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1123 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1124 if (lightInfo == NULL) {
1125 D3DLIGHT9 lightParms;
1126 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1127 wait until someone confirms it seems to work! */
1128 TRACE("Light enabled requested but light not defined, so defining one!\n");
1129 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1130 lightParms.Diffuse.r = 1.0;
1131 lightParms.Diffuse.g = 1.0;
1132 lightParms.Diffuse.b = 1.0;
1133 lightParms.Diffuse.a = 0.0;
1134 lightParms.Specular.r = 0.0;
1135 lightParms.Specular.g = 0.0;
1136 lightParms.Specular.b = 0.0;
1137 lightParms.Specular.a = 0.0;
1138 lightParms.Ambient.r = 0.0;
1139 lightParms.Ambient.g = 0.0;
1140 lightParms.Ambient.b = 0.0;
1141 lightParms.Ambient.a = 0.0;
1142 lightParms.Position.x = 0.0;
1143 lightParms.Position.y = 0.0;
1144 lightParms.Position.z = 0.0;
1145 lightParms.Direction.x = 0.0;
1146 lightParms.Direction.y = 0.0;
1147 lightParms.Direction.z = 1.0;
1148 lightParms.Range = 0.0;
1149 lightParms.Falloff = 0.0;
1150 lightParms.Attenuation0 = 0.0;
1151 lightParms.Attenuation1 = 0.0;
1152 lightParms.Attenuation2 = 0.0;
1153 lightParms.Theta = 0.0;
1154 lightParms.Phi = 0.0;
1155 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1157 /* Search for it again! Should be fairly quick as near head of list */
1158 lightInfo = This->stateBlock->lights;
1159 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1160 if (lightInfo == NULL) {
1161 FIXME("Adding default lights has failed dismally\n");
1162 return D3DERR_INVALIDCALL;
1166 /* OK, we now have a light... */
1167 if (Enable == FALSE) {
1169 /* If we are disabling it, check it was enabled, and
1170 still only do something if it has assigned a glIndex (which it should have!) */
1171 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1172 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1174 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1175 checkGLcall("glDisable GL_LIGHT0+Index");
1178 TRACE("Nothing to do as light was not enabled\n");
1180 lightInfo->lightEnabled = FALSE;
1183 /* We are enabling it. If it is enabled, it's really simple */
1184 if (lightInfo->lightEnabled) {
1186 TRACE("Nothing to do as light was enabled\n");
1188 /* If it already has a glIndex, it's still simple */
1189 } else if (lightInfo->glIndex != -1) {
1190 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1191 lightInfo->lightEnabled = TRUE;
1193 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1194 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1197 /* Otherwise got to find space - lights are ordered gl indexes first */
1199 PLIGHTINFOEL *bsf = NULL;
1200 PLIGHTINFOEL *pos = This->stateBlock->lights;
1201 PLIGHTINFOEL *prev = NULL;
1205 /* Try to minimize changes as much as possible */
1206 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1208 /* Try to remember which index can be replaced if necessary */
1209 if (bsf==NULL && pos->lightEnabled == FALSE) {
1210 /* Found a light we can replace, save as best replacement */
1214 /* Step to next space */
1220 /* If we have too many active lights, fail the call */
1221 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1222 FIXME("Program requests too many concurrent lights\n");
1223 return D3DERR_INVALIDCALL;
1225 /* If we have allocated all lights, but not all are enabled,
1226 reuse one which is not enabled */
1227 } else if (Index == This->maxConcurrentLights) {
1228 /* use bsf - Simply swap the new light and the BSF one */
1229 PLIGHTINFOEL *bsfNext = bsf->next;
1230 PLIGHTINFOEL *bsfPrev = bsf->prev;
1233 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1234 if (bsf->prev != NULL) {
1235 bsf->prev->next = lightInfo;
1237 This->stateBlock->lights = lightInfo;
1240 /* If not side by side, lots of chains to update */
1241 if (bsf->next != lightInfo) {
1242 lightInfo->prev->next = bsf;
1243 bsf->next->prev = lightInfo;
1244 bsf->next = lightInfo->next;
1245 bsf->prev = lightInfo->prev;
1246 lightInfo->next = bsfNext;
1247 lightInfo->prev = bsfPrev;
1251 bsf->prev = lightInfo;
1252 bsf->next = lightInfo->next;
1253 lightInfo->next = bsf;
1254 lightInfo->prev = bsfPrev;
1259 glIndex = bsf->glIndex;
1261 lightInfo->glIndex = glIndex;
1262 lightInfo->lightEnabled = TRUE;
1264 /* Finally set up the light in gl itself */
1265 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
1267 setup_light(iface, glIndex, lightInfo);
1268 glEnable(GL_LIGHT0 + glIndex);
1269 checkGLcall("glEnable GL_LIGHT0 new setup");
1272 /* If we reached the end of the allocated lights, with space in the
1273 gl lights, setup a new light */
1274 } else if (pos->glIndex == -1) {
1276 /* We reached the end of the allocated gl lights, so already
1277 know the index of the next one! */
1279 lightInfo->glIndex = glIndex;
1280 lightInfo->lightEnabled = TRUE;
1282 /* In an ideal world, it's already in the right place */
1283 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
1284 /* No need to move it */
1286 /* Remove this light from the list */
1287 lightInfo->prev->next = lightInfo->next;
1288 if (lightInfo->next != NULL) {
1289 lightInfo->next->prev = lightInfo->prev;
1292 /* Add in at appropriate place (inbetween prev and pos) */
1293 lightInfo->prev = prev;
1294 lightInfo->next = pos;
1296 This->stateBlock->lights = lightInfo;
1298 prev->next = lightInfo;
1301 pos->prev = lightInfo;
1305 /* Finally set up the light in gl itself */
1306 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
1308 setup_light(iface, glIndex, lightInfo);
1309 glEnable(GL_LIGHT0 + glIndex);
1310 checkGLcall("glEnable GL_LIGHT0 new setup");
1319 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
1321 PLIGHTINFOEL *lightInfo = NULL;
1322 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1323 TRACE("(%p) : for idx(%ld)\n", This, Index);
1325 /* Locate the light in the live lights */
1326 lightInfo = This->stateBlock->lights;
1327 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1329 if (lightInfo == NULL) {
1330 TRACE("Light enabled state requested but light not defined\n");
1331 return D3DERR_INVALIDCALL;
1333 *pEnable = lightInfo->lightEnabled;
1338 * Get / Set Clip Planes
1340 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
1341 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1342 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
1344 /* Validate Index */
1345 if (Index >= GL_LIMITS(clipplanes)) {
1346 TRACE("Application has requested clipplane this device doesn't support\n");
1347 return D3DERR_INVALIDCALL;
1350 This->updateStateBlock->changed.clipplane[Index] = TRUE;
1351 This->updateStateBlock->set.clipplane[Index] = TRUE;
1352 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
1353 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
1354 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
1355 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
1357 /* Handle recording of state blocks */
1358 if (This->isRecordingState) {
1359 TRACE("Recording... not performing anything\n");
1367 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
1368 glMatrixMode(GL_MODELVIEW);
1370 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1372 TRACE("Clipplane [%f,%f,%f,%f]\n",
1373 This->updateStateBlock->clipplane[Index][0],
1374 This->updateStateBlock->clipplane[Index][1],
1375 This->updateStateBlock->clipplane[Index][2],
1376 This->updateStateBlock->clipplane[Index][3]);
1377 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
1378 checkGLcall("glClipPlane");
1386 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
1387 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1388 TRACE("(%p) : for idx %ld\n", This, Index);
1390 /* Validate Index */
1391 if (Index >= GL_LIMITS(clipplanes)) {
1392 TRACE("Application has requested clipplane this device doesn't support\n");
1393 return D3DERR_INVALIDCALL;
1396 pPlane[0] = This->stateBlock->clipplane[Index][0];
1397 pPlane[1] = This->stateBlock->clipplane[Index][1];
1398 pPlane[2] = This->stateBlock->clipplane[Index][2];
1399 pPlane[3] = This->stateBlock->clipplane[Index][3];
1404 * Get / Set Clip Plane Status
1405 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
1407 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
1408 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1409 FIXME("(%p) : stub\n", This);
1410 if (NULL == pClipStatus) {
1411 return D3DERR_INVALIDCALL;
1413 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
1414 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
1418 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
1419 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1420 FIXME("(%p) : stub\n", This);
1421 if (NULL == pClipStatus) {
1422 return D3DERR_INVALIDCALL;
1424 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
1425 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
1430 * Get / Set Material
1431 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
1433 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
1434 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1436 This->updateStateBlock->changed.material = TRUE;
1437 This->updateStateBlock->set.material = TRUE;
1438 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
1440 /* Handle recording of state blocks */
1441 if (This->isRecordingState) {
1442 TRACE("Recording... not performing anything\n");
1447 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1448 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1449 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1450 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1451 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1453 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
1454 checkGLcall("glMaterialfv");
1455 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
1456 checkGLcall("glMaterialfv");
1458 /* Only change material color if specular is enabled, otherwise it is set to black */
1459 if (This->stateBlock->renderState[D3DRS_SPECULARENABLE]) {
1460 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1461 checkGLcall("glMaterialfv");
1463 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1464 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1465 checkGLcall("glMaterialfv");
1467 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
1468 checkGLcall("glMaterialfv");
1469 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
1470 checkGLcall("glMaterialf");
1476 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
1477 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1478 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
1479 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1480 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1481 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1482 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1483 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1490 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
1491 UINT BaseVertexIndex) {
1492 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1493 IWineD3DIndexBuffer *oldIdxs;
1495 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
1496 oldIdxs = This->updateStateBlock->pIndexData;
1498 This->updateStateBlock->changed.indices = TRUE;
1499 This->updateStateBlock->set.indices = TRUE;
1500 This->updateStateBlock->pIndexData = pIndexData;
1501 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
1503 /* Handle recording of state blocks */
1504 if (This->isRecordingState) {
1505 TRACE("Recording... not performing anything\n");
1509 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
1510 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
1514 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
1515 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1517 *ppIndexData = This->stateBlock->pIndexData;
1519 /* up ref count on ppindexdata */
1520 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
1521 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
1527 * Get / Set Viewports
1529 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
1530 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1532 TRACE("(%p)\n", This);
1533 This->updateStateBlock->changed.viewport = TRUE;
1534 This->updateStateBlock->set.viewport = TRUE;
1535 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
1537 /* Handle recording of state blocks */
1538 if (This->isRecordingState) {
1539 TRACE("Recording... not performing anything\n");
1545 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1546 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1548 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1549 checkGLcall("glDepthRange");
1551 /* Note: GL requires lower left, DirectX supplies upper left */
1552 glViewport(pViewport->X, (This->renderTarget->currentDesc.Height - (pViewport->Y + pViewport->Height)),
1553 pViewport->Width, pViewport->Height);
1554 checkGLcall("glViewport");
1562 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
1563 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1564 TRACE("(%p)\n", This);
1565 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
1570 * Get / Set Render States
1571 * TODO: Verify against dx9 definitions
1573 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
1575 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1576 DWORD OldValue = This->stateBlock->renderState[State];
1578 /* Simple way of referring to either a DWORD or a 4 byte float */
1584 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
1585 This->updateStateBlock->changed.renderState[State] = TRUE;
1586 This->updateStateBlock->set.renderState[State] = TRUE;
1587 This->updateStateBlock->renderState[State] = Value;
1589 /* Handle recording of state blocks */
1590 if (This->isRecordingState) {
1591 TRACE("Recording... not performing anything\n");
1598 case D3DRS_FILLMODE :
1599 switch ((D3DFILLMODE) Value) {
1600 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
1601 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
1602 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
1604 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
1606 checkGLcall("glPolygonMode (fillmode)");
1609 case D3DRS_LIGHTING :
1611 glEnable(GL_LIGHTING);
1612 checkGLcall("glEnable GL_LIGHTING");
1614 glDisable(GL_LIGHTING);
1615 checkGLcall("glDisable GL_LIGHTING");
1619 case D3DRS_ZENABLE :
1620 switch ((D3DZBUFFERTYPE) Value) {
1622 glDisable(GL_DEPTH_TEST);
1623 checkGLcall("glDisable GL_DEPTH_TEST");
1626 glEnable(GL_DEPTH_TEST);
1627 checkGLcall("glEnable GL_DEPTH_TEST");
1630 glEnable(GL_DEPTH_TEST);
1631 checkGLcall("glEnable GL_DEPTH_TEST");
1632 FIXME("W buffer is not well handled\n");
1635 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
1639 case D3DRS_CULLMODE :
1641 /* If we are culling "back faces with clockwise vertices" then
1642 set front faces to be counter clockwise and enable culling
1644 switch ((D3DCULL) Value) {
1646 glDisable(GL_CULL_FACE);
1647 checkGLcall("glDisable GL_CULL_FACE");
1650 glEnable(GL_CULL_FACE);
1651 checkGLcall("glEnable GL_CULL_FACE");
1652 if (This->renderUpsideDown) {
1654 checkGLcall("glFrontFace GL_CW");
1656 glFrontFace(GL_CCW);
1657 checkGLcall("glFrontFace GL_CCW");
1659 glCullFace(GL_BACK);
1662 glEnable(GL_CULL_FACE);
1663 checkGLcall("glEnable GL_CULL_FACE");
1664 if (This->renderUpsideDown) {
1665 glFrontFace(GL_CCW);
1666 checkGLcall("glFrontFace GL_CCW");
1669 checkGLcall("glFrontFace GL_CW");
1671 glCullFace(GL_BACK);
1674 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
1678 case D3DRS_SHADEMODE :
1679 switch ((D3DSHADEMODE) Value) {
1681 glShadeModel(GL_FLAT);
1682 checkGLcall("glShadeModel");
1684 case D3DSHADE_GOURAUD:
1685 glShadeModel(GL_SMOOTH);
1686 checkGLcall("glShadeModel");
1688 case D3DSHADE_PHONG:
1689 FIXME("D3DSHADE_PHONG isn't supported?\n");
1692 return D3DERR_INVALIDCALL;
1694 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
1698 case D3DRS_DITHERENABLE :
1700 glEnable(GL_DITHER);
1701 checkGLcall("glEnable GL_DITHER");
1703 glDisable(GL_DITHER);
1704 checkGLcall("glDisable GL_DITHER");
1708 case D3DRS_ZWRITEENABLE :
1711 checkGLcall("glDepthMask");
1714 checkGLcall("glDepthMask");
1720 int glParm = GL_LESS;
1722 switch ((D3DCMPFUNC) Value) {
1723 case D3DCMP_NEVER: glParm=GL_NEVER; break;
1724 case D3DCMP_LESS: glParm=GL_LESS; break;
1725 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
1726 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
1727 case D3DCMP_GREATER: glParm=GL_GREATER; break;
1728 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
1729 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
1730 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
1732 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1734 glDepthFunc(glParm);
1735 checkGLcall("glDepthFunc");
1739 case D3DRS_AMBIENT :
1742 D3DCOLORTOGLFLOAT4(Value, col);
1743 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
1744 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
1745 checkGLcall("glLightModel for MODEL_AMBIENT");
1750 case D3DRS_ALPHABLENDENABLE :
1753 checkGLcall("glEnable GL_BLEND");
1755 glDisable(GL_BLEND);
1756 checkGLcall("glDisable GL_BLEND");
1760 case D3DRS_SRCBLEND :
1761 case D3DRS_DESTBLEND :
1763 int newVal = GL_ZERO;
1765 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
1766 case D3DBLEND_ONE : newVal = GL_ONE; break;
1767 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
1768 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
1769 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
1770 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
1771 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
1772 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
1773 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
1774 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
1775 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
1777 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
1778 This->srcBlend = newVal;
1779 This->dstBlend = newVal;
1782 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
1783 This->srcBlend = newVal;
1784 This->dstBlend = newVal;
1787 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
1790 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
1791 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
1792 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
1793 glBlendFunc(This->srcBlend, This->dstBlend);
1795 checkGLcall("glBlendFunc");
1799 case D3DRS_ALPHATESTENABLE :
1801 glEnable(GL_ALPHA_TEST);
1802 checkGLcall("glEnable GL_ALPHA_TEST");
1804 glDisable(GL_ALPHA_TEST);
1805 checkGLcall("glDisable GL_ALPHA_TEST");
1809 case D3DRS_ALPHAFUNC :
1811 int glParm = GL_LESS;
1812 float ref = ((float) This->stateBlock->renderState[D3DRS_ALPHAREF]) / 255.0f;
1814 switch ((D3DCMPFUNC) Value) {
1815 case D3DCMP_NEVER: glParm = GL_NEVER; break;
1816 case D3DCMP_LESS: glParm = GL_LESS; break;
1817 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
1818 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
1819 case D3DCMP_GREATER: glParm = GL_GREATER; break;
1820 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
1821 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
1822 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
1824 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1826 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
1827 glAlphaFunc(glParm, ref);
1828 This->alphafunc = glParm;
1829 checkGLcall("glAlphaFunc");
1833 case D3DRS_ALPHAREF :
1835 int glParm = This->alphafunc;
1838 ref = ((float) Value) / 255.0f;
1839 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
1840 glAlphaFunc(glParm, ref);
1841 checkGLcall("glAlphaFunc");
1845 case D3DRS_CLIPPLANEENABLE :
1846 case D3DRS_CLIPPING :
1848 /* Ensure we only do the changed clip planes */
1849 DWORD enable = 0xFFFFFFFF;
1850 DWORD disable = 0x00000000;
1852 /* If enabling / disabling all */
1853 if (State == D3DRS_CLIPPING) {
1855 enable = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
1858 disable = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
1862 enable = Value & ~OldValue;
1863 disable = ~Value & OldValue;
1866 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
1867 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
1868 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
1869 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
1870 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
1871 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
1873 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
1874 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
1875 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
1876 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
1877 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
1878 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
1880 /** update clipping status */
1882 This->stateBlock->clip_status.ClipUnion = 0;
1883 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
1885 This->stateBlock->clip_status.ClipUnion = 0;
1886 This->stateBlock->clip_status.ClipIntersection = 0;
1891 case D3DRS_BLENDOP :
1893 int glParm = GL_FUNC_ADD;
1895 switch ((D3DBLENDOP) Value) {
1896 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
1897 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
1898 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
1899 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
1900 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
1902 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
1904 TRACE("glBlendEquation(%x)\n", glParm);
1905 glBlendEquation(glParm);
1906 checkGLcall("glBlendEquation");
1910 case D3DRS_TEXTUREFACTOR :
1914 /* Note the texture color applies to all textures whereas
1915 GL_TEXTURE_ENV_COLOR applies to active only */
1917 D3DCOLORTOGLFLOAT4(Value, col);
1918 /* Set the default alpha blend color */
1919 glBlendColor(col[0], col[1], col[2], col[3]);
1920 checkGLcall("glBlendColor");
1922 /* And now the default texture color as well */
1923 for (i = 0; i < GL_LIMITS(textures); i++) {
1925 /* Note the D3DRS value applies to all textures, but GL has one
1926 per texture, so apply it now ready to be used! */
1927 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1930 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1933 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1934 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1939 case D3DRS_SPECULARENABLE :
1941 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
1942 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
1943 specular color. This is wrong:
1944 Separate specular color means the specular colour is maintained separately, whereas
1945 single color means it is merged in. However in both cases they are being used to
1947 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
1948 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
1952 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1953 checkGLcall("glMaterialfv");
1954 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1955 glEnable(GL_COLOR_SUM_EXT);
1957 TRACE("Specular colors cannot be enabled in this version of opengl\n");
1959 checkGLcall("glEnable(GL_COLOR_SUM)");
1961 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1963 /* for the case of enabled lighting: */
1964 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1965 checkGLcall("glMaterialfv");
1967 /* for the case of disabled lighting: */
1968 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1969 glDisable(GL_COLOR_SUM_EXT);
1971 TRACE("Specular colors cannot be disabled in this version of opengl\n");
1973 checkGLcall("glDisable(GL_COLOR_SUM)");
1978 case D3DRS_STENCILENABLE :
1980 glEnable(GL_STENCIL_TEST);
1981 checkGLcall("glEnable GL_STENCIL_TEST");
1983 glDisable(GL_STENCIL_TEST);
1984 checkGLcall("glDisable GL_STENCIL_TEST");
1988 case D3DRS_STENCILFUNC :
1990 int glParm = GL_ALWAYS;
1991 int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
1992 GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
1994 switch ((D3DCMPFUNC) Value) {
1995 case D3DCMP_NEVER: glParm=GL_NEVER; break;
1996 case D3DCMP_LESS: glParm=GL_LESS; break;
1997 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
1998 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
1999 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2000 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2001 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2002 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2004 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2006 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2007 This->stencilfunc = glParm;
2008 glStencilFunc(glParm, ref, mask);
2009 checkGLcall("glStencilFunc");
2013 case D3DRS_STENCILREF :
2015 int glParm = This->stencilfunc;
2017 GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
2020 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2021 glStencilFunc(glParm, ref, mask);
2022 checkGLcall("glStencilFunc");
2026 case D3DRS_STENCILMASK :
2028 int glParm = This->stencilfunc;
2029 int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
2030 GLuint mask = Value;
2032 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2033 glStencilFunc(glParm, ref, mask);
2034 checkGLcall("glStencilFunc");
2038 case D3DRS_STENCILFAIL :
2044 fail = StencilOp(Value);
2045 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2046 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2047 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2048 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2050 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2051 glStencilOp(fail, zfail, zpass);
2052 checkGLcall("glStencilOp(fail, zfail, zpass);");
2055 case D3DRS_STENCILZFAIL :
2061 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2062 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2063 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2064 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2065 zfail = StencilOp(Value);
2067 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2068 glStencilOp(fail, zfail, zpass);
2069 checkGLcall("glStencilOp(fail, zfail, zpass);");
2072 case D3DRS_STENCILPASS :
2078 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2079 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2080 zpass = StencilOp(Value);
2081 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2082 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2084 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2085 glStencilOp(fail, zfail, zpass);
2086 checkGLcall("glStencilOp(fail, zfail, zpass);");
2090 case D3DRS_STENCILWRITEMASK :
2092 glStencilMask(Value);
2093 TRACE("glStencilMask(%lu)\n", Value);
2094 checkGLcall("glStencilMask");
2098 case D3DRS_FOGENABLE :
2100 if (Value/* && This->stateBlock->renderState[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2102 checkGLcall("glEnable GL_FOG");
2105 checkGLcall("glDisable GL_FOG");
2110 case D3DRS_RANGEFOGENABLE :
2113 TRACE("Enabled RANGEFOG");
2115 TRACE("Disabled RANGEFOG");
2120 case D3DRS_FOGCOLOR :
2123 D3DCOLORTOGLFLOAT4(Value, col);
2124 /* Set the default alpha blend color */
2125 glFogfv(GL_FOG_COLOR, &col[0]);
2126 checkGLcall("glFog GL_FOG_COLOR");
2130 case D3DRS_FOGTABLEMODE :
2132 glHint(GL_FOG_HINT, GL_NICEST);
2134 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2135 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2136 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2137 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2139 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2141 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2142 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2147 case D3DRS_FOGVERTEXMODE :
2149 glHint(GL_FOG_HINT, GL_FASTEST);
2151 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2152 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2153 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2154 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2156 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2158 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2159 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2164 case D3DRS_FOGSTART :
2167 glFogfv(GL_FOG_START, &tmpvalue.f);
2168 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2169 TRACE("Fog Start == %f\n", tmpvalue.f);
2176 glFogfv(GL_FOG_END, &tmpvalue.f);
2177 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2178 TRACE("Fog End == %f\n", tmpvalue.f);
2182 case D3DRS_FOGDENSITY :
2185 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2186 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2190 case D3DRS_VERTEXBLEND :
2192 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2193 TRACE("Vertex Blending state to %ld\n", Value);
2197 case D3DRS_TWEENFACTOR :
2200 This->updateStateBlock->tween_factor = tmpvalue.f;
2201 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2205 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2207 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2211 case D3DRS_COLORVERTEX :
2212 case D3DRS_DIFFUSEMATERIALSOURCE :
2213 case D3DRS_SPECULARMATERIALSOURCE :
2214 case D3DRS_AMBIENTMATERIALSOURCE :
2215 case D3DRS_EMISSIVEMATERIALSOURCE :
2217 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2219 if (This->stateBlock->renderState[D3DRS_COLORVERTEX]) {
2220 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2221 This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE],
2222 This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE],
2223 This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE],
2224 This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE]);
2226 if (This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2227 if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2228 Parm = GL_AMBIENT_AND_DIFFUSE;
2232 } else if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2234 } else if (This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2236 } else if (This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2243 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2245 This->tracking_color = NEEDS_TRACKING;
2246 This->tracking_parm = Parm;
2250 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2255 case D3DRS_LINEPATTERN :
2261 tmppattern.d = Value;
2263 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2265 if (tmppattern.lp.wRepeatFactor) {
2266 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2267 checkGLcall("glLineStipple(repeat, linepattern)");
2268 glEnable(GL_LINE_STIPPLE);
2269 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2271 glDisable(GL_LINE_STIPPLE);
2272 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2281 TRACE("ZBias value %f\n", tmpvalue.f);
2282 glPolygonOffset(0, -tmpvalue.f);
2283 checkGLcall("glPolygonOffset(0, -Value)");
2284 glEnable(GL_POLYGON_OFFSET_FILL);
2285 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2286 glEnable(GL_POLYGON_OFFSET_LINE);
2287 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2288 glEnable(GL_POLYGON_OFFSET_POINT);
2289 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2291 glDisable(GL_POLYGON_OFFSET_FILL);
2292 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2293 glDisable(GL_POLYGON_OFFSET_LINE);
2294 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2295 glDisable(GL_POLYGON_OFFSET_POINT);
2296 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2301 case D3DRS_NORMALIZENORMALS :
2303 glEnable(GL_NORMALIZE);
2304 checkGLcall("glEnable(GL_NORMALIZE);");
2306 glDisable(GL_NORMALIZE);
2307 checkGLcall("glDisable(GL_NORMALIZE);");
2311 case D3DRS_POINTSIZE :
2313 TRACE("Set point size to %f\n", tmpvalue.f);
2314 glPointSize(tmpvalue.f);
2315 checkGLcall("glPointSize(...);");
2318 case D3DRS_POINTSIZE_MIN :
2319 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2321 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2322 checkGLcall("glPointParameterfEXT(...);");
2324 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2328 case D3DRS_POINTSIZE_MAX :
2329 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2331 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2332 checkGLcall("glPointParameterfEXT(...);");
2334 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2338 case D3DRS_POINTSCALE_A :
2339 case D3DRS_POINTSCALE_B :
2340 case D3DRS_POINTSCALE_C :
2341 case D3DRS_POINTSCALEENABLE :
2343 /* If enabled, supply the parameters, otherwise fall back to defaults */
2344 if (This->stateBlock->renderState[D3DRS_POINTSCALEENABLE]) {
2345 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2346 att[0] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_A]);
2347 att[1] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_B]);
2348 att[2] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_C]);
2350 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2351 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2352 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2354 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2357 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2358 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2359 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2360 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2362 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2368 case D3DRS_COLORWRITEENABLE :
2370 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2371 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2372 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2373 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2374 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2375 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2376 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2377 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2378 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2379 checkGLcall("glColorMask(...)");
2383 case D3DRS_LOCALVIEWER :
2385 GLint state = (Value) ? 1 : 0;
2386 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
2387 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
2391 case D3DRS_LASTPIXEL :
2394 TRACE("Last Pixel Drawing Enabled\n");
2396 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
2401 case D3DRS_SOFTWAREVERTEXPROCESSING :
2404 TRACE("Software Processing Enabled\n");
2406 TRACE("Software Processing Disabled\n");
2411 /** not supported */
2412 case D3DRS_ZVISIBLE :
2415 return D3DERR_INVALIDCALL;
2418 /* Unhandled yet...! */
2419 case D3DRS_EDGEANTIALIAS :
2428 case D3DRS_POINTSPRITEENABLE :
2429 case D3DRS_MULTISAMPLEANTIALIAS :
2430 case D3DRS_MULTISAMPLEMASK :
2431 case D3DRS_PATCHEDGESTYLE :
2432 case D3DRS_PATCHSEGMENTS :
2433 case D3DRS_DEBUGMONITORTOKEN :
2434 case D3DRS_POSITIONORDER :
2435 case D3DRS_NORMALORDER :
2436 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2437 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2440 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2448 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
2449 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2450 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
2451 *pValue = This->stateBlock->renderState[State];
2457 * Get / Set Texture Stage States
2458 * TODO: Verify against dx9 definitions
2460 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
2461 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2467 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
2469 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
2471 /* Reject invalid texture units */
2472 if (Stage >= GL_LIMITS(textures)) {
2473 TRACE("Attempt to access invalid texture rejected\n");
2474 return D3DERR_INVALIDCALL;
2477 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
2478 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
2479 This->updateStateBlock->textureState[Stage][Type] = Value;
2481 /* Handle recording of state blocks */
2482 if (This->isRecordingState) {
2483 TRACE("Recording... not performing anything\n");
2489 /* Make appropriate texture active */
2490 VTRACE(("Activating appropriate texture state %ld\n", Stage));
2491 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2492 GLACTIVETEXTURE(Stage);
2493 } else if (Stage > 0) {
2494 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2499 case D3DTSS_MINFILTER :
2500 case D3DTSS_MIPFILTER :
2502 DWORD ValueMIN = This->stateBlock->textureState[Stage][D3DTSS_MINFILTER];
2503 DWORD ValueMIP = This->stateBlock->textureState[Stage][D3DTSS_MIPFILTER];
2504 GLint realVal = GL_LINEAR;
2506 if (ValueMIN == D3DTEXF_NONE) {
2507 /* Doesn't really make sense - Windows just seems to disable
2508 mipmapping when this occurs */
2509 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
2510 realVal = GL_LINEAR;
2511 } else if (ValueMIN == D3DTEXF_POINT) {
2513 if (ValueMIP == D3DTEXF_NONE) {
2514 realVal = GL_NEAREST;
2515 } else if (ValueMIP == D3DTEXF_POINT) {
2516 realVal = GL_NEAREST_MIPMAP_NEAREST;
2517 } else if (ValueMIP == D3DTEXF_LINEAR) {
2518 realVal = GL_NEAREST_MIPMAP_LINEAR;
2520 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2521 realVal = GL_NEAREST;
2523 } else if (ValueMIN == D3DTEXF_LINEAR) {
2525 if (ValueMIP == D3DTEXF_NONE) {
2526 realVal = GL_LINEAR;
2527 } else if (ValueMIP == D3DTEXF_POINT) {
2528 realVal = GL_LINEAR_MIPMAP_NEAREST;
2529 } else if (ValueMIP == D3DTEXF_LINEAR) {
2530 realVal = GL_LINEAR_MIPMAP_LINEAR;
2532 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2533 realVal = GL_LINEAR;
2535 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
2536 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2537 if (ValueMIP == D3DTEXF_NONE) {
2538 realVal = GL_LINEAR_MIPMAP_LINEAR;
2539 } else if (ValueMIP == D3DTEXF_POINT) {
2540 realVal = GL_LINEAR_MIPMAP_NEAREST;
2541 } else if (ValueMIP == D3DTEXF_LINEAR) {
2542 realVal = GL_LINEAR_MIPMAP_LINEAR;
2544 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2545 realVal = GL_LINEAR;
2548 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
2549 realVal = GL_LINEAR;
2552 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
2553 realVal = GL_LINEAR_MIPMAP_LINEAR;
2556 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
2557 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
2558 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
2560 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
2562 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
2563 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2564 GL_TEXTURE_MAX_ANISOTROPY_EXT,
2565 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2566 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
2571 case D3DTSS_MAGFILTER :
2573 DWORD ValueMAG = This->stateBlock->textureState[Stage][D3DTSS_MAGFILTER];
2574 GLint realVal = GL_NEAREST;
2576 if (ValueMAG == D3DTEXF_POINT) {
2577 realVal = GL_NEAREST;
2578 } else if (ValueMAG == D3DTEXF_LINEAR) {
2579 realVal = GL_LINEAR;
2580 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
2581 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2582 realVal = GL_LINEAR;
2584 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
2585 realVal = GL_NEAREST;
2588 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
2589 realVal = GL_NEAREST;
2591 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
2592 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
2593 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
2595 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
2597 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
2598 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2599 GL_TEXTURE_MAX_ANISOTROPY_EXT,
2600 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2601 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
2606 case D3DTSS_MAXMIPLEVEL :
2609 * Not really the same, but the more apprioprate than nothing
2611 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2612 GL_TEXTURE_BASE_LEVEL,
2613 This->stateBlock->textureState[Stage][D3DTSS_MAXMIPLEVEL]);
2614 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
2618 case D3DTSS_MAXANISOTROPY :
2620 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2621 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2622 GL_TEXTURE_MAX_ANISOTROPY_EXT,
2623 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2624 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
2629 case D3DTSS_MIPMAPLODBIAS :
2631 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2633 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2634 GL_TEXTURE_LOD_BIAS_EXT,
2636 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
2641 case D3DTSS_ALPHAOP :
2642 case D3DTSS_COLOROP :
2645 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
2646 /* TODO: Disable by making this and all later levels disabled */
2647 glDisable(GL_TEXTURE_1D);
2648 checkGLcall("Disable GL_TEXTURE_1D");
2649 glDisable(GL_TEXTURE_2D);
2650 checkGLcall("Disable GL_TEXTURE_2D");
2651 glDisable(GL_TEXTURE_3D);
2652 checkGLcall("Disable GL_TEXTURE_3D");
2653 break; /* Don't bother setting the texture operations */
2655 /* Enable only the appropriate texture dimension */
2656 if (Type == D3DTSS_COLOROP) {
2657 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2658 glEnable(GL_TEXTURE_1D);
2659 checkGLcall("Enable GL_TEXTURE_1D");
2661 glDisable(GL_TEXTURE_1D);
2662 checkGLcall("Disable GL_TEXTURE_1D");
2664 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
2665 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
2666 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
2667 checkGLcall("Enable GL_TEXTURE_2D");
2669 glEnable(GL_TEXTURE_2D);
2670 checkGLcall("Enable GL_TEXTURE_2D");
2673 glDisable(GL_TEXTURE_2D);
2674 checkGLcall("Disable GL_TEXTURE_2D");
2676 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
2677 glEnable(GL_TEXTURE_3D);
2678 checkGLcall("Enable GL_TEXTURE_3D");
2680 glDisable(GL_TEXTURE_3D);
2681 checkGLcall("Disable GL_TEXTURE_3D");
2683 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
2684 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
2685 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
2687 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2688 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
2692 /* Drop through... (Except disable case) */
2693 case D3DTSS_COLORARG0 :
2694 case D3DTSS_COLORARG1 :
2695 case D3DTSS_COLORARG2 :
2696 case D3DTSS_ALPHAARG0 :
2697 case D3DTSS_ALPHAARG1 :
2698 case D3DTSS_ALPHAARG2 :
2700 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
2701 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
2703 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP],
2704 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1],
2705 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG2],
2706 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG0]);
2708 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][D3DTSS_COLOROP],
2709 This->stateBlock->textureState[Stage][D3DTSS_COLORARG1],
2710 This->stateBlock->textureState[Stage][D3DTSS_COLORARG2],
2711 This->stateBlock->textureState[Stage][D3DTSS_COLORARG0]);
2717 case D3DTSS_ADDRESSU :
2718 case D3DTSS_ADDRESSV :
2719 case D3DTSS_ADDRESSW :
2721 GLint wrapParm = GL_REPEAT;
2724 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
2725 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
2726 case D3DTADDRESS_BORDER:
2728 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2729 wrapParm = GL_CLAMP_TO_BORDER_ARB;
2731 /* FIXME: Not right, but better */
2732 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
2733 wrapParm = GL_REPEAT;
2737 case D3DTADDRESS_MIRROR:
2739 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2740 wrapParm = GL_MIRRORED_REPEAT_ARB;
2742 /* Unsupported in OpenGL pre-1.4 */
2743 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
2744 wrapParm = GL_REPEAT;
2748 case D3DTADDRESS_MIRRORONCE:
2750 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2751 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
2753 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
2754 wrapParm = GL_REPEAT;
2760 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
2761 wrapParm = GL_REPEAT;
2765 case D3DTSS_ADDRESSU:
2766 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2767 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
2768 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
2770 case D3DTSS_ADDRESSV:
2771 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2772 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
2773 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
2775 case D3DTSS_ADDRESSW:
2776 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2777 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
2778 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
2781 break; /** stupic compilator */
2786 case D3DTSS_BORDERCOLOR :
2789 D3DCOLORTOGLFLOAT4(Value, col);
2790 TRACE("Setting border color for %x to %lx\n", This->stateBlock->textureDimensions[Stage], Value);
2791 glTexParameterfv(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
2792 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
2796 case D3DTSS_TEXCOORDINDEX :
2798 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
2800 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
2801 one flag, you can still specify an index value, which the system uses to
2802 determine the texture wrapping mode.
2803 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2804 means use the vertex position (camera-space) as the input texture coordinates
2805 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
2806 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
2807 to the TEXCOORDINDEX value */
2810 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
2812 switch (Value & 0xFFFF0000) {
2813 case D3DTSS_TCI_PASSTHRU:
2814 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2815 glDisable(GL_TEXTURE_GEN_S);
2816 glDisable(GL_TEXTURE_GEN_T);
2817 glDisable(GL_TEXTURE_GEN_R);
2818 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
2821 case D3DTSS_TCI_CAMERASPACEPOSITION:
2822 /* CameraSpacePosition means use the vertex position, transformed to camera space,
2823 as the input texture coordinates for this stage's texture transformation. This
2824 equates roughly to EYE_LINEAR */
2826 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2827 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2828 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2829 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2830 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2832 glMatrixMode(GL_MODELVIEW);
2835 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2836 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2837 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2838 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2841 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2842 glEnable(GL_TEXTURE_GEN_S);
2843 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2844 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2845 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2846 glEnable(GL_TEXTURE_GEN_T);
2847 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2848 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2849 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2850 glEnable(GL_TEXTURE_GEN_R);
2851 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2852 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2853 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2857 case D3DTSS_TCI_CAMERASPACENORMAL:
2859 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2860 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2861 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2862 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2863 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2864 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2866 glMatrixMode(GL_MODELVIEW);
2869 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2870 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2871 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2872 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2875 glEnable(GL_TEXTURE_GEN_S);
2876 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2877 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2878 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2879 glEnable(GL_TEXTURE_GEN_T);
2880 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2881 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2882 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2883 glEnable(GL_TEXTURE_GEN_R);
2884 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2885 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2886 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2891 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2893 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2894 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2895 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2896 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2897 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2898 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2900 glMatrixMode(GL_MODELVIEW);
2903 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2904 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2905 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2906 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2909 glEnable(GL_TEXTURE_GEN_S);
2910 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2911 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2912 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2913 glEnable(GL_TEXTURE_GEN_T);
2914 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2915 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2916 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2917 glEnable(GL_TEXTURE_GEN_R);
2918 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2919 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2920 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2925 /* Unhandled types: */
2928 /* ? disable GL_TEXTURE_GEN_n ? */
2929 glDisable(GL_TEXTURE_GEN_S);
2930 glDisable(GL_TEXTURE_GEN_T);
2931 glDisable(GL_TEXTURE_GEN_R);
2932 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
2939 case D3DTSS_TEXTURETRANSFORMFLAGS :
2940 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
2943 case D3DTSS_BUMPENVMAT00 :
2944 case D3DTSS_BUMPENVMAT01 :
2945 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
2947 case D3DTSS_BUMPENVMAT10 :
2948 case D3DTSS_BUMPENVMAT11 :
2949 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
2952 case D3DTSS_BUMPENVLSCALE :
2953 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2956 case D3DTSS_BUMPENVLOFFSET :
2957 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2960 case D3DTSS_RESULTARG :
2961 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2965 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
2966 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2974 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
2975 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2976 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
2977 *pValue = This->updateStateBlock->textureState[Stage][Type];
2984 HRESULT WINAPI IWineD3DDeviceImpl_SetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture* pTexture) {
2986 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2987 IWineD3DBaseTexture *oldTexture;
2988 BOOL reapplyStates = TRUE;
2989 DWORD reapplyFlags = 0;
2990 INT oldTextureDimensions = -1;
2991 D3DRESOURCETYPE textureType;
2993 oldTexture = This->updateStateBlock->textures[Stage];
2994 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
2996 /* Reject invalid texture units */
2997 if (Stage >= GL_LIMITS(textures)) {
2998 TRACE("Attempt to access invalid texture rejected\n");
2999 return D3DERR_INVALIDCALL;
3002 This->updateStateBlock->set.textures[Stage] = TRUE;
3003 This->updateStateBlock->changed.textures[Stage] = TRUE;
3004 This->updateStateBlock->textures[Stage] = pTexture;
3006 /* Handle recording of state blocks */
3007 if (This->isRecordingState) {
3008 TRACE("Recording... not performing anything\n");
3012 oldTextureDimensions = This->updateStateBlock->textureDimensions[Stage];
3016 /* Make appropriate texture active */
3017 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3018 GLACTIVETEXTURE(Stage);
3020 } else if (Stage>0) {
3021 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3024 /* Decrement the count of the previous texture */
3025 if (NULL != oldTexture) {
3026 IWineD3DBaseTexture_Release(oldTexture);
3029 if (NULL != pTexture) {
3030 IWineD3DBaseTexture_AddRef((IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage]);
3032 /* Now setup the texture appropraitly */
3033 textureType = IWineD3DBaseTexture_GetType(pTexture);
3035 if (textureType == D3DRTYPE_TEXTURE) {
3037 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3038 TRACE("Skipping setting texture as old == new\n");
3039 reapplyStates = FALSE;
3043 /* Standard 2D texture */
3044 TRACE("Standard 2d texture\n");
3045 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3047 /* Load up the texture now */
3048 IWineD3DTexture_PreLoad((IWineD3DTexture *) pTexture);
3051 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3053 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3054 TRACE("Skipping setting texture as old == new\n");
3055 reapplyStates = FALSE;
3059 /* Standard 3D (volume) texture */
3060 TRACE("Standard 3d texture\n");
3061 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3063 /* Load up the texture now */
3064 IWineD3DVolumeTexture_PreLoad((IWineD3DVolumeTexture *) pTexture);
3067 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3069 if (oldTexture == pTexture && !IWineD3DBaseTexture_GetDirty(pTexture)) {
3070 TRACE("Skipping setting texture as old == new\n");
3071 reapplyStates = FALSE;
3075 /* Standard Cube texture */
3076 TRACE("Standard Cube texture\n");
3077 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3079 /* Load up the texture now */
3080 IWineD3DCubeTexture_PreLoad((IWineD3DCubeTexture *) pTexture);
3084 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dresourcetype(textureType));
3089 TRACE("Setting to no texture (ie default texture)\n");
3090 This->updateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3091 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3092 checkGLcall("glBindTexture");
3093 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3096 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3097 if (oldTextureDimensions != This->updateStateBlock->textureDimensions[Stage]) {
3099 glDisable(oldTextureDimensions);
3100 checkGLcall("Disable oldTextureDimensions");
3102 if (This->stateBlock->textureState[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3103 glEnable(This->updateStateBlock->textureDimensions[Stage]);
3104 checkGLcall("glEnable new texture dimensions");
3107 /* If Alpha arg1 is texture then handle the special case when there changes between a
3108 texture and no texture - See comments in set_tex_op */
3109 if ((This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3110 (((oldTexture == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTexture != NULL))))
3112 reapplyFlags |= REAPPLY_ALPHAOP;
3117 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3118 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3119 if (reapplyStates) {
3120 IWineD3DDeviceImpl_SetupTextureStates(iface, Stage, reapplyFlags);
3124 TRACE("Texture now fully setup\n");
3129 HRESULT WINAPI IWineD3DDeviceImpl_GetTexture(IWineD3DDevice *iface, DWORD Stage, IWineD3DBaseTexture** ppTexture) {
3130 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3131 TRACE("(%p) : returning %p for stage %ld\n", This, This->updateStateBlock->textures[Stage], Stage);
3132 *ppTexture = (IWineD3DBaseTexture *) This->updateStateBlock->textures[Stage];
3134 IWineD3DBaseTexture_AddRef(*ppTexture);
3141 HRESULT WINAPI IWineD3DDeviceImpl_GetBackBuffer(IWineD3DDevice *iface, UINT iSwapChain, UINT BackBuffer, D3DBACKBUFFER_TYPE Type,
3142 IWineD3DSurface** ppBackBuffer) {
3143 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3145 *ppBackBuffer = (IWineD3DSurface *) This->backBuffer;
3146 TRACE("(%p) : BackBuf %d Type %d SwapChain %d returning %p\n", This, BackBuffer, Type, iSwapChain, *ppBackBuffer);
3148 if (BackBuffer > This->presentParms.BackBufferCount - 1) {
3149 FIXME("Only one backBuffer currently supported\n");
3150 return D3DERR_INVALIDCALL;
3153 /* Note inc ref on returned surface */
3154 IWineD3DSurface_AddRef(*ppBackBuffer);
3159 HRESULT WINAPI IWineD3DDeviceImpl_GetDeviceCaps(IWineD3DDevice *iface, D3DCAPS9* pCaps) {
3160 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3161 WARN("(%p) : stub, calling idirect3d for now\n", This);
3162 IWineD3D_GetDeviceCaps(This->wineD3D, This->adapterNo, This->devType, pCaps);
3166 HRESULT WINAPI IWineD3DDeviceImpl_GetDisplayMode(IWineD3DDevice *iface, UINT iSwapChain, D3DDISPLAYMODE* pMode) {
3167 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3171 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
3172 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
3173 pMode->RefreshRate = 85; /*FIXME: How to identify? */
3175 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
3176 bpp = GetDeviceCaps(hdc, BITSPIXEL);
3180 case 8: pMode->Format = D3DFMT_R8G8B8; break;
3181 case 16: pMode->Format = D3DFMT_R5G6B5; break;
3182 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
3183 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
3185 FIXME("Unrecognized display mode format\n");
3186 pMode->Format = D3DFMT_UNKNOWN;
3189 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
3190 pMode->Format, debug_d3dformat(pMode->Format));
3195 * Scene related functions
3197 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
3198 /* At the moment we have no need for any functionality at the beginning
3200 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3201 TRACE("(%p) : stub\n", This);
3205 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
3206 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3207 TRACE("(%p)\n", This);
3212 checkGLcall("glFlush");
3214 if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
3216 /* If we are rendering to a texture (surface) then flag it as dirty.
3217 A surfaces container is either the appropriate texture or the device itself
3218 depending on how the surface was created. */
3219 if (This->renderTarget != NULL && ((IWineD3DDeviceImpl *)This->renderTarget->container != This)) {
3221 IWineD3DBaseTexture *cont = (IWineD3DBaseTexture *)This->renderTarget->container;
3222 /** always dirtify for now. we must find a better way to see that surface have been modified */
3223 This->renderTarget->inPBuffer = TRUE;
3224 This->renderTarget->inTexture = FALSE;
3225 IWineD3DBaseTexture_SetDirty(cont, TRUE);
3226 IWineD3DBaseTexture_PreLoad(cont);
3227 This->renderTarget->inPBuffer = FALSE;
3235 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
3236 CONST RECT* pSourceRect, CONST RECT* pDestRect,
3237 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
3238 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3239 TRACE("(%p) Presenting the frame\n", This);
3243 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
3245 glXSwapBuffers(This->display, This->drawable);
3246 /* Don't call checkGLcall, as glGetError is not applicable here */
3248 TRACE("glXSwapBuffers called, Starting new frame\n");
3251 if (TRACE_ON(d3d_fps))
3253 static long prev_time, frames;
3255 DWORD time = GetTickCount();
3257 /* every 1.5 seconds */
3258 if (time - prev_time > 1500) {
3259 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
3265 #if defined(FRAME_DEBUGGING)
3267 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
3270 FIXME("Enabling D3D Trace\n");
3271 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
3272 #if defined(SHOW_FRAME_MAKEUP)
3273 FIXME("Singe Frame snapshots Starting\n");
3274 isDumpingFrames = TRUE;
3275 glClear(GL_COLOR_BUFFER_BIT);
3278 #if defined(SINGLE_FRAME_DEBUGGING)
3280 #if defined(SHOW_FRAME_MAKEUP)
3281 FIXME("Singe Frame snapshots Finishing\n");
3282 isDumpingFrames = FALSE;
3284 FIXME("Singe Frame trace complete\n");
3285 DeleteFileA("C:\\D3DTRACE");
3286 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3292 #if defined(SHOW_FRAME_MAKEUP)
3293 FIXME("Singe Frame snapshots Finishing\n");
3294 isDumpingFrames = FALSE;
3296 FIXME("Disabling D3D Trace\n");
3297 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3304 /* Although this is not strictly required, a simple demo showed this does occur
3305 on (at least non-debug) d3d */
3306 if (This->presentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
3307 IWineD3DDevice_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
3313 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
3314 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
3315 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3317 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
3318 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
3319 when the depth-buffer format does not contain stencil buffer information, this method fails. */
3320 GLbitfield glMask = 0;
3321 GLboolean old_ztest;
3322 GLfloat old_z_clear_value;
3323 GLint old_stencil_clear_value;
3324 GLfloat old_color_clear_value[4];
3326 CONST D3DRECT* curRect;
3328 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
3329 Count, pRects, Flags, Z, Stencil);
3333 glEnable(GL_SCISSOR_TEST);
3334 checkGLcall("glEnable GL_SCISSOR_TEST");
3336 if (Count > 0 && pRects) {
3342 /* Only set the values up once, as they are not changing */
3343 if (Flags & D3DCLEAR_STENCIL) {
3344 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
3345 glClearStencil(Stencil);
3346 checkGLcall("glClearStencil");
3347 glMask = glMask | GL_STENCIL_BUFFER_BIT;
3348 glStencilMask(0xFFFFFFFF);
3351 if (Flags & D3DCLEAR_ZBUFFER) {
3352 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
3353 glDepthMask(GL_TRUE);
3354 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
3356 checkGLcall("glClearDepth");
3357 glMask = glMask | GL_DEPTH_BUFFER_BIT;
3360 if (Flags & D3DCLEAR_TARGET) {
3361 TRACE("Clearing screen with glClear to color %lx\n", Color);
3362 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
3363 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
3364 ((Color >> 8) & 0xFF) / 255.0f,
3365 ((Color >> 0) & 0xFF) / 255.0f,
3366 ((Color >> 24) & 0xFF) / 255.0f);
3367 checkGLcall("glClearColor");
3369 /* Clear ALL colors! */
3370 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3371 glMask = glMask | GL_COLOR_BUFFER_BIT;
3374 /* Now process each rect in turn */
3375 for (i = 0; i < Count || i == 0; i++) {
3378 /* Note gl uses lower left, width/height */
3379 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
3380 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
3381 curRect->x1, (This->renderTarget->currentDesc.Height - curRect->y2),
3382 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3383 glScissor(curRect->x1, (This->renderTarget->currentDesc.Height - curRect->y2),
3384 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3385 checkGLcall("glScissor");
3387 glScissor(This->stateBlock->viewport.X,
3388 (This->renderTarget->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
3389 This->stateBlock->viewport.Width,
3390 This->stateBlock->viewport.Height);
3391 checkGLcall("glScissor");
3394 /* Clear the selected rectangle (or full screen) */
3396 checkGLcall("glClear");
3398 /* Step to the next rectangle */
3399 if (curRect) curRect = curRect + sizeof(D3DRECT);
3402 /* Restore the old values (why..?) */
3403 if (Flags & D3DCLEAR_STENCIL) {
3404 glClearStencil(old_stencil_clear_value);
3405 glStencilMask(This->stateBlock->renderState[D3DRS_STENCILWRITEMASK]);
3407 if (Flags & D3DCLEAR_ZBUFFER) {
3408 glDepthMask(old_ztest);
3409 glClearDepth(old_z_clear_value);
3411 if (Flags & D3DCLEAR_TARGET) {
3412 glClearColor(old_color_clear_value[0],
3413 old_color_clear_value[1],
3414 old_color_clear_value[2],
3415 old_color_clear_value[3]);
3416 glColorMask(This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3417 This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3418 This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3419 This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3422 glDisable(GL_SCISSOR_TEST);
3423 checkGLcall("glDisable");
3432 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
3433 UINT PrimitiveCount) {
3435 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3436 This->stateBlock->streamIsUP = FALSE;
3438 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
3439 debug_d3dprimitivetype(PrimitiveType),
3440 StartVertex, PrimitiveCount);
3441 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3446 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
3447 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
3448 D3DPRIMITIVETYPE PrimitiveType,
3449 INT baseVIndex, UINT minIndex,
3450 UINT NumVertices,UINT startIndex,UINT primCount) {
3452 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3454 IWineD3DIndexBuffer *pIB;
3455 D3DINDEXBUFFER_DESC IdxBufDsc;
3457 pIB = This->stateBlock->pIndexData;
3458 This->stateBlock->streamIsUP = FALSE;
3460 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
3461 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3462 minIndex, NumVertices, startIndex, baseVIndex, primCount);
3464 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
3465 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3471 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
3472 startIndex, idxStride,
3473 ((IWineD3DIndexBufferImpl *) pIB)->allocatedMemory,
3479 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
3480 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
3481 UINT VertexStreamZeroStride) {
3482 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3484 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
3485 debug_d3dprimitivetype(PrimitiveType),
3486 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3488 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
3490 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
3491 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
3492 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
3493 This->stateBlock->streamIsUP = TRUE;
3494 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3495 This->stateBlock->stream_stride[0] = 0;
3496 This->stateBlock->stream_source[0] = NULL;
3498 /*stream zero settings set to null at end, as per the msdn */
3502 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
3503 UINT MinVertexIndex,
3504 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3505 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3506 UINT VertexStreamZeroStride) {
3508 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3510 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
3511 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3512 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
3513 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3515 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
3517 if (IndexDataFormat == D3DFMT_INDEX16) {
3523 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
3524 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
3525 This->stateBlock->streamIsUP = TRUE;
3526 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
3528 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
3530 /* stream zero settings set to null at end as per the msdn */
3531 This->stateBlock->stream_source[0] = NULL;
3532 This->stateBlock->stream_stride[0] = 0;
3533 IWineD3DDevice_SetIndices(iface, NULL, 0);
3538 /**********************************************************
3539 * IUnknown parts follows
3540 **********************************************************/
3542 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
3544 return E_NOINTERFACE;
3547 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
3548 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3549 ULONG refCount = InterlockedIncrement(&This->ref);
3551 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
3555 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
3556 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3557 ULONG refCount = InterlockedDecrement(&This->ref);
3559 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
3562 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
3563 IWineD3D_Release(This->wineD3D);
3564 HeapFree(GetProcessHeap(), 0, This);
3569 /**********************************************************
3570 * IWineD3DDevice VTbl follows
3571 **********************************************************/
3573 IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
3575 IWineD3DDeviceImpl_QueryInterface,
3576 IWineD3DDeviceImpl_AddRef,
3577 IWineD3DDeviceImpl_Release,
3578 IWineD3DDeviceImpl_GetParent,
3579 IWineD3DDeviceImpl_CreateVertexBuffer,
3580 IWineD3DDeviceImpl_CreateIndexBuffer,
3581 IWineD3DDeviceImpl_CreateStateBlock,
3582 IWineD3DDeviceImpl_CreateRenderTarget,
3583 IWineD3DDeviceImpl_CreateOffscreenPlainSurface,
3584 IWineD3DDeviceImpl_CreateTexture,
3585 IWineD3DDeviceImpl_CreateVolumeTexture,
3586 IWineD3DDeviceImpl_CreateVolume,
3587 IWineD3DDeviceImpl_CreateCubeTexture,
3589 IWineD3DDeviceImpl_SetFVF,
3590 IWineD3DDeviceImpl_GetFVF,
3591 IWineD3DDeviceImpl_SetStreamSource,
3592 IWineD3DDeviceImpl_GetStreamSource,
3593 IWineD3DDeviceImpl_SetTransform,
3594 IWineD3DDeviceImpl_GetTransform,
3595 IWineD3DDeviceImpl_MultiplyTransform,
3596 IWineD3DDeviceImpl_SetLight,
3597 IWineD3DDeviceImpl_GetLight,
3598 IWineD3DDeviceImpl_SetLightEnable,
3599 IWineD3DDeviceImpl_GetLightEnable,
3600 IWineD3DDeviceImpl_SetClipPlane,
3601 IWineD3DDeviceImpl_GetClipPlane,
3602 IWineD3DDeviceImpl_SetClipStatus,
3603 IWineD3DDeviceImpl_GetClipStatus,
3604 IWineD3DDeviceImpl_SetMaterial,
3605 IWineD3DDeviceImpl_GetMaterial,
3606 IWineD3DDeviceImpl_SetIndices,
3607 IWineD3DDeviceImpl_GetIndices,
3608 IWineD3DDeviceImpl_SetViewport,
3609 IWineD3DDeviceImpl_GetViewport,
3610 IWineD3DDeviceImpl_SetRenderState,
3611 IWineD3DDeviceImpl_GetRenderState,
3612 IWineD3DDeviceImpl_SetTextureStageState,
3613 IWineD3DDeviceImpl_GetTextureStageState,
3614 IWineD3DDeviceImpl_SetTexture,
3615 IWineD3DDeviceImpl_GetTexture,
3617 IWineD3DDeviceImpl_GetBackBuffer,
3618 IWineD3DDeviceImpl_GetDeviceCaps,
3619 IWineD3DDeviceImpl_GetDisplayMode,
3621 IWineD3DDeviceImpl_BeginScene,
3622 IWineD3DDeviceImpl_EndScene,
3623 IWineD3DDeviceImpl_Present,
3624 IWineD3DDeviceImpl_Clear,
3626 IWineD3DDeviceImpl_DrawPrimitive,
3627 IWineD3DDeviceImpl_DrawIndexedPrimitive,
3628 IWineD3DDeviceImpl_DrawPrimitiveUP,
3629 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
3631 IWineD3DDeviceImpl_SetupTextureStates