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 *ppCubeTexture = NULL;
623 return D3DERR_OUTOFVIDEOMEMORY;
626 object->lpVtbl = &IWineD3DCubeTexture_Vtbl;
627 object->resource.wineD3DDevice = This;
628 IWineD3DDevice_AddRef(iface);
629 object->resource.resourceType = D3DRTYPE_CUBETEXTURE;
630 object->resource.parent = parent;
631 object->resource.ref = 1;
632 *ppCubeTexture = (IWineD3DCubeTexture *)object;
634 /* Allocate the storage for it */
635 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));
637 object->usage = Usage;
638 object->edgeLength = EdgeLength;
639 object->baseTexture.levels = Levels;
640 object->baseTexture.format = Format;
642 /* Calculate levels for mip mapping */
644 object->baseTexture.levels++;
647 tmpW = max(1, tmpW / 2);
648 object->baseTexture.levels++;
650 TRACE("Calculated levels = %d\n", object->baseTexture.levels);
653 /* Generate all the surfaces */
655 for (i = 0; i < object->baseTexture.levels; i++) {
657 /* Create the 6 faces */
658 for (j = 0; j < 6; j++) {
660 D3DCB_CreateSurface(This->parent, tmpW, tmpW, Format, Pool,
661 (IWineD3DSurface **)&object->surfaces[j][i], pSharedHandle);
662 object->surfaces[j][i]->container = (IUnknown*) object;
663 object->surfaces[j][i]->currentDesc.Usage = Usage;
664 object->surfaces[j][i]->currentDesc.Pool = Pool;
667 * As written in msdn in IDirect3DCubeTexture8::LockRect
668 * Textures created in D3DPOOL_DEFAULT are not lockable.
670 if (D3DPOOL_DEFAULT == Pool) {
671 object->surfaces[j][i]->lockable = FALSE;
674 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
676 tmpW = max(1, tmpW / 2);
679 TRACE("(%p) : Created Cube Texture %p\n", This, object);
680 *ppCubeTexture = (IWineD3DCubeTexture *) object;
687 HRESULT WINAPI IWineD3DDeviceImpl_SetFVF(IWineD3DDevice *iface, DWORD fvf) {
688 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
690 /* Update the current statte block */
691 This->updateStateBlock->fvf = fvf;
692 This->updateStateBlock->changed.fvf = TRUE;
693 This->updateStateBlock->set.fvf = TRUE;
695 TRACE("(%p) : FVF Shader FVF set to %lx\n", This, fvf);
697 /* No difference if recording or not */
700 HRESULT WINAPI IWineD3DDeviceImpl_GetFVF(IWineD3DDevice *iface, DWORD *pfvf) {
701 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
702 TRACE("(%p) : GetFVF returning %lx\n", This, This->stateBlock->fvf);
703 *pfvf = This->stateBlock->fvf;
708 * Get / Set Stream Source
710 HRESULT WINAPI IWineD3DDeviceImpl_SetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer* pStreamData, UINT OffsetInBytes, UINT Stride) {
711 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
712 IWineD3DVertexBuffer *oldSrc;
714 oldSrc = This->stateBlock->stream_source[StreamNumber];
715 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
717 This->updateStateBlock->changed.stream_source[StreamNumber] = TRUE;
718 This->updateStateBlock->set.stream_source[StreamNumber] = TRUE;
719 This->updateStateBlock->stream_stride[StreamNumber] = Stride;
720 This->updateStateBlock->stream_source[StreamNumber] = pStreamData;
721 This->updateStateBlock->stream_offset[StreamNumber] = OffsetInBytes;
723 /* Handle recording of state blocks */
724 if (This->isRecordingState) {
725 TRACE("Recording... not performing anything\n");
729 /* Not recording... */
730 if (oldSrc != NULL) IWineD3DVertexBuffer_Release(oldSrc);
731 if (pStreamData != NULL) IWineD3DVertexBuffer_AddRef(pStreamData);
736 HRESULT WINAPI IWineD3DDeviceImpl_GetStreamSource(IWineD3DDevice *iface, UINT StreamNumber,IWineD3DVertexBuffer** pStream, UINT *pOffset, UINT* pStride) {
737 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
739 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->stateBlock->stream_source[StreamNumber], This->stateBlock->stream_stride[StreamNumber]);
740 *pStream = This->stateBlock->stream_source[StreamNumber];
741 *pStride = This->stateBlock->stream_stride[StreamNumber];
742 *pOffset = This->stateBlock->stream_offset[StreamNumber];
743 IWineD3DVertexBuffer_AddRef(*pStream); /* We have created a new reference to the VB */
748 * Get / Set & Multipy Transform
750 HRESULT WINAPI IWineD3DDeviceImpl_SetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
751 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
753 /* Most of this routine, comments included copied from ddraw tree initially: */
754 TRACE("(%p) : Transform State=%d\n", This, d3dts);
756 /* Handle recording of state blocks */
757 if (This->isRecordingState) {
758 TRACE("Recording... not performing anything\n");
759 This->updateStateBlock->changed.transform[d3dts] = TRUE;
760 This->updateStateBlock->set.transform[d3dts] = TRUE;
761 memcpy(&This->updateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
766 * If the new matrix is the same as the current one,
767 * we cut off any further processing. this seems to be a reasonable
768 * optimization because as was noticed, some apps (warcraft3 for example)
769 * tend towards setting the same matrix repeatedly for some reason.
771 * From here on we assume that the new matrix is different, wherever it matters.
773 if (!memcmp(&This->stateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
774 TRACE("The app is setting the same matrix over again\n");
777 conv_mat(lpmatrix, &This->stateBlock->transforms[d3dts].u.m[0][0]);
781 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
782 where ViewMat = Camera space, WorldMat = world space.
784 In OpenGL, camera and world space is combined into GL_MODELVIEW
785 matrix. The Projection matrix stay projection matrix.
788 /* Capture the times we can just ignore the change for now */
789 if (d3dts == D3DTS_WORLDMATRIX(0)) {
790 This->modelview_valid = FALSE;
793 } else if (d3dts == D3DTS_PROJECTION) {
794 This->proj_valid = FALSE;
797 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) {
798 /* Indexed Vertex Blending Matrices 256 -> 511 */
799 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
800 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
804 /* Now we really are going to have to change a matrix */
807 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
808 if (d3dts < GL_LIMITS(textures)) {
809 int tex = d3dts - D3DTS_TEXTURE0;
810 GLACTIVETEXTURE(tex);
811 set_texture_matrix((float *)lpmatrix,
812 This->updateStateBlock->textureState[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
815 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
818 /* If we are changing the View matrix, reset the light and clipping planes to the new view
819 * NOTE: We have to reset the positions even if the light/plane is not currently
820 * enabled, since the call to enable it will not reset the position.
821 * NOTE2: Apparently texture transforms do NOT need reapplying
824 PLIGHTINFOEL *lightChain = NULL;
825 This->modelview_valid = FALSE;
826 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
828 glMatrixMode(GL_MODELVIEW);
829 checkGLcall("glMatrixMode(GL_MODELVIEW)");
831 glLoadMatrixf((float *)lpmatrix);
832 checkGLcall("glLoadMatrixf(...)");
835 lightChain = This->stateBlock->lights;
836 while (lightChain && lightChain->glIndex != -1) {
837 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
838 checkGLcall("glLightfv posn");
839 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
840 checkGLcall("glLightfv dirn");
841 lightChain = lightChain->next;
844 /* Reset Clipping Planes if clipping is enabled */
845 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
846 glClipPlane(GL_CLIP_PLANE0 + k, This->stateBlock->clipplane[k]);
847 checkGLcall("glClipPlane");
851 } else { /* What was requested!?? */
852 WARN("invalid matrix specified: %i\n", d3dts);
855 /* Release lock, all done */
860 HRESULT WINAPI IWineD3DDeviceImpl_GetTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix) {
861 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
862 TRACE("(%p) : for Transform State %d\n", This, State);
863 memcpy(pMatrix, &This->stateBlock->transforms[State], sizeof(D3DMATRIX));
867 HRESULT WINAPI IWineD3DDeviceImpl_MultiplyTransform(IWineD3DDevice *iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
868 D3DMATRIX *mat = NULL;
871 /* Note: Using 'updateStateBlock' rather than 'stateblock' in the code
872 * below means it will be recorded in a state block change, but it
873 * works regardless where it is recorded.
874 * If this is found to be wrong, change to StateBlock.
876 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
877 TRACE("(%p) : For state %u\n", This, State);
879 if (State < HIGHEST_TRANSFORMSTATE)
881 mat = &This->updateStateBlock->transforms[State];
883 FIXME("Unhandled transform state!!\n");
886 /* Copied from ddraw code: */
887 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);
888 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);
889 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);
890 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);
892 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);
893 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);
894 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);
895 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);
897 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);
898 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);
899 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);
900 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);
902 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);
903 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);
904 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);
905 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);
907 /* Apply change via set transform - will reapply to eg. lights this way */
908 IWineD3DDeviceImpl_SetTransform(iface, State, &temp);
914 * WARNING: This code relies on the fact that D3DLIGHT8 == D3DLIGHT9
916 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
917 you can reference any indexes you want as long as that number max are enabled at any
918 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
919 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
920 but when recording, just build a chain pretty much of commands to be replayed. */
922 HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD Index, CONST WINED3DLIGHT* pLight) {
924 PLIGHTINFOEL *object, *temp;
926 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
927 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
929 /* If recording state block, just add to end of lights chain */
930 if (This->isRecordingState) {
931 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
932 if (NULL == object) {
933 return D3DERR_OUTOFVIDEOMEMORY;
935 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
936 object->OriginalIndex = Index;
937 object->glIndex = -1;
938 object->changed = TRUE;
940 /* Add to the END of the chain of lights changes to be replayed */
941 if (This->updateStateBlock->lights == NULL) {
942 This->updateStateBlock->lights = object;
944 temp = This->updateStateBlock->lights;
945 while (temp->next != NULL) temp=temp->next;
948 TRACE("Recording... not performing anything more\n");
952 /* Ok, not recording any longer so do real work */
953 object = This->stateBlock->lights;
954 while (object != NULL && object->OriginalIndex != Index) object = object->next;
956 /* If we didn't find it in the list of lights, time to add it */
957 if (object == NULL) {
958 PLIGHTINFOEL *insertAt,*prevPos;
960 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
961 if (NULL == object) {
962 return D3DERR_OUTOFVIDEOMEMORY;
964 object->OriginalIndex = Index;
965 object->glIndex = -1;
967 /* Add it to the front of list with the idea that lights will be changed as needed
968 BUT after any lights currently assigned GL indexes */
969 insertAt = This->stateBlock->lights;
971 while (insertAt != NULL && insertAt->glIndex != -1) {
973 insertAt = insertAt->next;
976 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
977 This->stateBlock->lights = object;
978 } else if (insertAt == NULL) { /* End of list */
979 prevPos->next = object;
980 object->prev = prevPos;
981 } else { /* Middle of chain */
982 if (prevPos == NULL) {
983 This->stateBlock->lights = object;
985 prevPos->next = object;
987 object->prev = prevPos;
988 object->next = insertAt;
989 insertAt->prev = object;
993 /* Initialze the object */
994 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,
995 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
996 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
997 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
998 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
999 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1000 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1002 /* Save away the information */
1003 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT9));
1005 switch (pLight->Type) {
1006 case D3DLIGHT_POINT:
1008 object->lightPosn[0] = pLight->Position.x;
1009 object->lightPosn[1] = pLight->Position.y;
1010 object->lightPosn[2] = pLight->Position.z;
1011 object->lightPosn[3] = 1.0f;
1012 object->cutoff = 180.0f;
1016 case D3DLIGHT_DIRECTIONAL:
1018 object->lightPosn[0] = -pLight->Direction.x;
1019 object->lightPosn[1] = -pLight->Direction.y;
1020 object->lightPosn[2] = -pLight->Direction.z;
1021 object->lightPosn[3] = 0.0;
1022 object->exponent = 0.0f;
1023 object->cutoff = 180.0f;
1028 object->lightPosn[0] = pLight->Position.x;
1029 object->lightPosn[1] = pLight->Position.y;
1030 object->lightPosn[2] = pLight->Position.z;
1031 object->lightPosn[3] = 1.0;
1034 object->lightDirn[0] = pLight->Direction.x;
1035 object->lightDirn[1] = pLight->Direction.y;
1036 object->lightDirn[2] = pLight->Direction.z;
1037 object->lightDirn[3] = 1.0;
1040 * opengl-ish and d3d-ish spot lights use too different models for the
1041 * light "intensity" as a function of the angle towards the main light direction,
1042 * so we only can approximate very roughly.
1043 * however spot lights are rather rarely used in games (if ever used at all).
1044 * furthermore if still used, probably nobody pays attention to such details.
1046 if (pLight->Falloff == 0) {
1049 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1051 if (rho < 0.0001) rho = 0.0001f;
1052 object->exponent = -0.3/log(cos(rho/2));
1053 object->cutoff = pLight->Phi*90/M_PI;
1059 FIXME("Unrecognized light type %d\n", pLight->Type);
1062 /* Update the live definitions if the light is currently assigned a glIndex */
1063 if (object->glIndex != -1) {
1064 setup_light(iface, object->glIndex, object);
1069 HRESULT WINAPI IWineD3DDeviceImpl_GetLight(IWineD3DDevice *iface, DWORD Index, WINED3DLIGHT* pLight) {
1070 PLIGHTINFOEL *lightInfo = NULL;
1071 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1072 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1074 /* Locate the light in the live lights */
1075 lightInfo = This->stateBlock->lights;
1076 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1078 if (lightInfo == NULL) {
1079 TRACE("Light information requested but light not defined\n");
1080 return D3DERR_INVALIDCALL;
1083 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT9));
1088 * Get / Set Light Enable
1089 * (Note for consistency, renamed d3dx function by adding the 'set' prefix)
1091 HRESULT WINAPI IWineD3DDeviceImpl_SetLightEnable(IWineD3DDevice *iface, DWORD Index, BOOL Enable) {
1092 PLIGHTINFOEL *lightInfo = NULL;
1093 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1094 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1096 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1097 if (This->isRecordingState) {
1098 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1099 if (NULL == lightInfo) {
1100 return D3DERR_OUTOFVIDEOMEMORY;
1102 lightInfo->OriginalIndex = Index;
1103 lightInfo->glIndex = -1;
1104 lightInfo->enabledChanged = TRUE;
1106 /* Add to the END of the chain of lights changes to be replayed */
1107 if (This->updateStateBlock->lights == NULL) {
1108 This->updateStateBlock->lights = lightInfo;
1110 PLIGHTINFOEL *temp = This->updateStateBlock->lights;
1111 while (temp->next != NULL) temp=temp->next;
1112 temp->next = lightInfo;
1114 TRACE("Recording... not performing anything more\n");
1118 /* Not recording... So, locate the light in the live lights */
1119 lightInfo = This->stateBlock->lights;
1120 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1122 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1123 if (lightInfo == NULL) {
1124 D3DLIGHT9 lightParms;
1125 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1126 wait until someone confirms it seems to work! */
1127 TRACE("Light enabled requested but light not defined, so defining one!\n");
1128 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1129 lightParms.Diffuse.r = 1.0;
1130 lightParms.Diffuse.g = 1.0;
1131 lightParms.Diffuse.b = 1.0;
1132 lightParms.Diffuse.a = 0.0;
1133 lightParms.Specular.r = 0.0;
1134 lightParms.Specular.g = 0.0;
1135 lightParms.Specular.b = 0.0;
1136 lightParms.Specular.a = 0.0;
1137 lightParms.Ambient.r = 0.0;
1138 lightParms.Ambient.g = 0.0;
1139 lightParms.Ambient.b = 0.0;
1140 lightParms.Ambient.a = 0.0;
1141 lightParms.Position.x = 0.0;
1142 lightParms.Position.y = 0.0;
1143 lightParms.Position.z = 0.0;
1144 lightParms.Direction.x = 0.0;
1145 lightParms.Direction.y = 0.0;
1146 lightParms.Direction.z = 1.0;
1147 lightParms.Range = 0.0;
1148 lightParms.Falloff = 0.0;
1149 lightParms.Attenuation0 = 0.0;
1150 lightParms.Attenuation1 = 0.0;
1151 lightParms.Attenuation2 = 0.0;
1152 lightParms.Theta = 0.0;
1153 lightParms.Phi = 0.0;
1154 IWineD3DDeviceImpl_SetLight(iface, Index, &lightParms);
1156 /* Search for it again! Should be fairly quick as near head of list */
1157 lightInfo = This->stateBlock->lights;
1158 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1159 if (lightInfo == NULL) {
1160 FIXME("Adding default lights has failed dismally\n");
1161 return D3DERR_INVALIDCALL;
1165 /* OK, we now have a light... */
1166 if (Enable == FALSE) {
1168 /* If we are disabling it, check it was enabled, and
1169 still only do something if it has assigned a glIndex (which it should have!) */
1170 if ((lightInfo->lightEnabled) && (lightInfo->glIndex != -1)) {
1171 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1173 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1174 checkGLcall("glDisable GL_LIGHT0+Index");
1177 TRACE("Nothing to do as light was not enabled\n");
1179 lightInfo->lightEnabled = FALSE;
1182 /* We are enabling it. If it is enabled, it's really simple */
1183 if (lightInfo->lightEnabled) {
1185 TRACE("Nothing to do as light was enabled\n");
1187 /* If it already has a glIndex, it's still simple */
1188 } else if (lightInfo->glIndex != -1) {
1189 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1190 lightInfo->lightEnabled = TRUE;
1192 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1193 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1196 /* Otherwise got to find space - lights are ordered gl indexes first */
1198 PLIGHTINFOEL *bsf = NULL;
1199 PLIGHTINFOEL *pos = This->stateBlock->lights;
1200 PLIGHTINFOEL *prev = NULL;
1204 /* Try to minimize changes as much as possible */
1205 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1207 /* Try to remember which index can be replaced if necessary */
1208 if (bsf==NULL && pos->lightEnabled == FALSE) {
1209 /* Found a light we can replace, save as best replacement */
1213 /* Step to next space */
1219 /* If we have too many active lights, fail the call */
1220 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1221 FIXME("Program requests too many concurrent lights\n");
1222 return D3DERR_INVALIDCALL;
1224 /* If we have allocated all lights, but not all are enabled,
1225 reuse one which is not enabled */
1226 } else if (Index == This->maxConcurrentLights) {
1227 /* use bsf - Simply swap the new light and the BSF one */
1228 PLIGHTINFOEL *bsfNext = bsf->next;
1229 PLIGHTINFOEL *bsfPrev = bsf->prev;
1232 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1233 if (bsf->prev != NULL) {
1234 bsf->prev->next = lightInfo;
1236 This->stateBlock->lights = lightInfo;
1239 /* If not side by side, lots of chains to update */
1240 if (bsf->next != lightInfo) {
1241 lightInfo->prev->next = bsf;
1242 bsf->next->prev = lightInfo;
1243 bsf->next = lightInfo->next;
1244 bsf->prev = lightInfo->prev;
1245 lightInfo->next = bsfNext;
1246 lightInfo->prev = bsfPrev;
1250 bsf->prev = lightInfo;
1251 bsf->next = lightInfo->next;
1252 lightInfo->next = bsf;
1253 lightInfo->prev = bsfPrev;
1258 glIndex = bsf->glIndex;
1260 lightInfo->glIndex = glIndex;
1261 lightInfo->lightEnabled = TRUE;
1263 /* Finally set up the light in gl itself */
1264 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
1266 setup_light(iface, glIndex, lightInfo);
1267 glEnable(GL_LIGHT0 + glIndex);
1268 checkGLcall("glEnable GL_LIGHT0 new setup");
1271 /* If we reached the end of the allocated lights, with space in the
1272 gl lights, setup a new light */
1273 } else if (pos->glIndex == -1) {
1275 /* We reached the end of the allocated gl lights, so already
1276 know the index of the next one! */
1278 lightInfo->glIndex = glIndex;
1279 lightInfo->lightEnabled = TRUE;
1281 /* In an ideal world, it's already in the right place */
1282 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
1283 /* No need to move it */
1285 /* Remove this light from the list */
1286 lightInfo->prev->next = lightInfo->next;
1287 if (lightInfo->next != NULL) {
1288 lightInfo->next->prev = lightInfo->prev;
1291 /* Add in at appropriate place (inbetween prev and pos) */
1292 lightInfo->prev = prev;
1293 lightInfo->next = pos;
1295 This->stateBlock->lights = lightInfo;
1297 prev->next = lightInfo;
1300 pos->prev = lightInfo;
1304 /* Finally set up the light in gl itself */
1305 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
1307 setup_light(iface, glIndex, lightInfo);
1308 glEnable(GL_LIGHT0 + glIndex);
1309 checkGLcall("glEnable GL_LIGHT0 new setup");
1318 HRESULT WINAPI IWineD3DDeviceImpl_GetLightEnable(IWineD3DDevice *iface, DWORD Index,BOOL* pEnable) {
1320 PLIGHTINFOEL *lightInfo = NULL;
1321 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1322 TRACE("(%p) : for idx(%ld)\n", This, Index);
1324 /* Locate the light in the live lights */
1325 lightInfo = This->stateBlock->lights;
1326 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1328 if (lightInfo == NULL) {
1329 TRACE("Light enabled state requested but light not defined\n");
1330 return D3DERR_INVALIDCALL;
1332 *pEnable = lightInfo->lightEnabled;
1337 * Get / Set Clip Planes
1339 HRESULT WINAPI IWineD3DDeviceImpl_SetClipPlane(IWineD3DDevice *iface, DWORD Index, CONST float *pPlane) {
1340 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1341 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
1343 /* Validate Index */
1344 if (Index >= GL_LIMITS(clipplanes)) {
1345 TRACE("Application has requested clipplane this device doesn't support\n");
1346 return D3DERR_INVALIDCALL;
1349 This->updateStateBlock->changed.clipplane[Index] = TRUE;
1350 This->updateStateBlock->set.clipplane[Index] = TRUE;
1351 This->updateStateBlock->clipplane[Index][0] = pPlane[0];
1352 This->updateStateBlock->clipplane[Index][1] = pPlane[1];
1353 This->updateStateBlock->clipplane[Index][2] = pPlane[2];
1354 This->updateStateBlock->clipplane[Index][3] = pPlane[3];
1356 /* Handle recording of state blocks */
1357 if (This->isRecordingState) {
1358 TRACE("Recording... not performing anything\n");
1366 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
1367 glMatrixMode(GL_MODELVIEW);
1369 glLoadMatrixf((float *) &This->stateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1371 TRACE("Clipplane [%f,%f,%f,%f]\n",
1372 This->updateStateBlock->clipplane[Index][0],
1373 This->updateStateBlock->clipplane[Index][1],
1374 This->updateStateBlock->clipplane[Index][2],
1375 This->updateStateBlock->clipplane[Index][3]);
1376 glClipPlane(GL_CLIP_PLANE0 + Index, This->updateStateBlock->clipplane[Index]);
1377 checkGLcall("glClipPlane");
1385 HRESULT WINAPI IWineD3DDeviceImpl_GetClipPlane(IWineD3DDevice *iface, DWORD Index, float *pPlane) {
1386 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1387 TRACE("(%p) : for idx %ld\n", This, Index);
1389 /* Validate Index */
1390 if (Index >= GL_LIMITS(clipplanes)) {
1391 TRACE("Application has requested clipplane this device doesn't support\n");
1392 return D3DERR_INVALIDCALL;
1395 pPlane[0] = This->stateBlock->clipplane[Index][0];
1396 pPlane[1] = This->stateBlock->clipplane[Index][1];
1397 pPlane[2] = This->stateBlock->clipplane[Index][2];
1398 pPlane[3] = This->stateBlock->clipplane[Index][3];
1403 * Get / Set Clip Plane Status
1404 * WARNING: This code relies on the fact that D3DCLIPSTATUS8 == D3DCLIPSTATUS9
1406 HRESULT WINAPI IWineD3DDeviceImpl_SetClipStatus(IWineD3DDevice *iface, CONST WINED3DCLIPSTATUS* pClipStatus) {
1407 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1408 FIXME("(%p) : stub\n", This);
1409 if (NULL == pClipStatus) {
1410 return D3DERR_INVALIDCALL;
1412 This->updateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
1413 This->updateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
1417 HRESULT WINAPI IWineD3DDeviceImpl_GetClipStatus(IWineD3DDevice *iface, WINED3DCLIPSTATUS* pClipStatus) {
1418 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1419 FIXME("(%p) : stub\n", This);
1420 if (NULL == pClipStatus) {
1421 return D3DERR_INVALIDCALL;
1423 pClipStatus->ClipUnion = This->updateStateBlock->clip_status.ClipUnion;
1424 pClipStatus->ClipIntersection = This->updateStateBlock->clip_status.ClipIntersection;
1429 * Get / Set Material
1430 * WARNING: This code relies on the fact that D3DMATERIAL8 == D3DMATERIAL9
1432 HRESULT WINAPI IWineD3DDeviceImpl_SetMaterial(IWineD3DDevice *iface, CONST WINED3DMATERIAL* pMaterial) {
1433 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1435 This->updateStateBlock->changed.material = TRUE;
1436 This->updateStateBlock->set.material = TRUE;
1437 memcpy(&This->updateStateBlock->material, pMaterial, sizeof(WINED3DMATERIAL));
1439 /* Handle recording of state blocks */
1440 if (This->isRecordingState) {
1441 TRACE("Recording... not performing anything\n");
1446 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1447 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1448 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1449 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1450 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1452 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->updateStateBlock->material.Ambient);
1453 checkGLcall("glMaterialfv");
1454 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->updateStateBlock->material.Diffuse);
1455 checkGLcall("glMaterialfv");
1457 /* Only change material color if specular is enabled, otherwise it is set to black */
1458 if (This->stateBlock->renderState[D3DRS_SPECULARENABLE]) {
1459 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1460 checkGLcall("glMaterialfv");
1462 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1463 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1464 checkGLcall("glMaterialfv");
1466 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->updateStateBlock->material.Emissive);
1467 checkGLcall("glMaterialfv");
1468 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->updateStateBlock->material.Power);
1469 checkGLcall("glMaterialf");
1475 HRESULT WINAPI IWineD3DDeviceImpl_GetMaterial(IWineD3DDevice *iface, WINED3DMATERIAL* pMaterial) {
1476 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1477 memcpy(pMaterial, &This->updateStateBlock->material, sizeof (WINED3DMATERIAL));
1478 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1479 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1480 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1481 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1482 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1489 HRESULT WINAPI IWineD3DDeviceImpl_SetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer* pIndexData,
1490 UINT BaseVertexIndex) {
1491 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1492 IWineD3DIndexBuffer *oldIdxs;
1494 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
1495 oldIdxs = This->updateStateBlock->pIndexData;
1497 This->updateStateBlock->changed.indices = TRUE;
1498 This->updateStateBlock->set.indices = TRUE;
1499 This->updateStateBlock->pIndexData = pIndexData;
1500 This->updateStateBlock->baseVertexIndex = BaseVertexIndex;
1502 /* Handle recording of state blocks */
1503 if (This->isRecordingState) {
1504 TRACE("Recording... not performing anything\n");
1508 if (oldIdxs) IWineD3DIndexBuffer_Release(oldIdxs);
1509 if (pIndexData) IWineD3DIndexBuffer_AddRef(This->stateBlock->pIndexData);
1513 HRESULT WINAPI IWineD3DDeviceImpl_GetIndices(IWineD3DDevice *iface, IWineD3DIndexBuffer** ppIndexData, UINT* pBaseVertexIndex) {
1514 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1516 *ppIndexData = This->stateBlock->pIndexData;
1518 /* up ref count on ppindexdata */
1519 if (*ppIndexData) IWineD3DIndexBuffer_AddRef(*ppIndexData);
1520 *pBaseVertexIndex = This->stateBlock->baseVertexIndex;
1526 * Get / Set Viewports
1528 HRESULT WINAPI IWineD3DDeviceImpl_SetViewport(IWineD3DDevice *iface, CONST WINED3DVIEWPORT* pViewport) {
1529 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1531 TRACE("(%p)\n", This);
1532 This->updateStateBlock->changed.viewport = TRUE;
1533 This->updateStateBlock->set.viewport = TRUE;
1534 memcpy(&This->updateStateBlock->viewport, pViewport, sizeof(WINED3DVIEWPORT));
1536 /* Handle recording of state blocks */
1537 if (This->isRecordingState) {
1538 TRACE("Recording... not performing anything\n");
1544 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1545 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1547 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1548 checkGLcall("glDepthRange");
1550 /* Note: GL requires lower left, DirectX supplies upper left */
1551 glViewport(pViewport->X, (This->renderTarget->currentDesc.Height - (pViewport->Y + pViewport->Height)),
1552 pViewport->Width, pViewport->Height);
1553 checkGLcall("glViewport");
1561 HRESULT WINAPI IWineD3DDeviceImpl_GetViewport(IWineD3DDevice *iface, WINED3DVIEWPORT* pViewport) {
1562 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1563 TRACE("(%p)\n", This);
1564 memcpy(pViewport, &This->stateBlock->viewport, sizeof(WINED3DVIEWPORT));
1569 * Get / Set Render States
1570 * TODO: Verify against dx9 definitions
1572 HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD Value) {
1574 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1575 DWORD OldValue = This->stateBlock->renderState[State];
1577 /* Simple way of referring to either a DWORD or a 4 byte float */
1583 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
1584 This->updateStateBlock->changed.renderState[State] = TRUE;
1585 This->updateStateBlock->set.renderState[State] = TRUE;
1586 This->updateStateBlock->renderState[State] = Value;
1588 /* Handle recording of state blocks */
1589 if (This->isRecordingState) {
1590 TRACE("Recording... not performing anything\n");
1597 case D3DRS_FILLMODE :
1598 switch ((D3DFILLMODE) Value) {
1599 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
1600 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
1601 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
1603 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
1605 checkGLcall("glPolygonMode (fillmode)");
1608 case D3DRS_LIGHTING :
1610 glEnable(GL_LIGHTING);
1611 checkGLcall("glEnable GL_LIGHTING");
1613 glDisable(GL_LIGHTING);
1614 checkGLcall("glDisable GL_LIGHTING");
1618 case D3DRS_ZENABLE :
1619 switch ((D3DZBUFFERTYPE) Value) {
1621 glDisable(GL_DEPTH_TEST);
1622 checkGLcall("glDisable GL_DEPTH_TEST");
1625 glEnable(GL_DEPTH_TEST);
1626 checkGLcall("glEnable GL_DEPTH_TEST");
1629 glEnable(GL_DEPTH_TEST);
1630 checkGLcall("glEnable GL_DEPTH_TEST");
1631 FIXME("W buffer is not well handled\n");
1634 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
1638 case D3DRS_CULLMODE :
1640 /* If we are culling "back faces with clockwise vertices" then
1641 set front faces to be counter clockwise and enable culling
1643 switch ((D3DCULL) Value) {
1645 glDisable(GL_CULL_FACE);
1646 checkGLcall("glDisable GL_CULL_FACE");
1649 glEnable(GL_CULL_FACE);
1650 checkGLcall("glEnable GL_CULL_FACE");
1651 if (This->renderUpsideDown) {
1653 checkGLcall("glFrontFace GL_CW");
1655 glFrontFace(GL_CCW);
1656 checkGLcall("glFrontFace GL_CCW");
1658 glCullFace(GL_BACK);
1661 glEnable(GL_CULL_FACE);
1662 checkGLcall("glEnable GL_CULL_FACE");
1663 if (This->renderUpsideDown) {
1664 glFrontFace(GL_CCW);
1665 checkGLcall("glFrontFace GL_CCW");
1668 checkGLcall("glFrontFace GL_CW");
1670 glCullFace(GL_BACK);
1673 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
1677 case D3DRS_SHADEMODE :
1678 switch ((D3DSHADEMODE) Value) {
1680 glShadeModel(GL_FLAT);
1681 checkGLcall("glShadeModel");
1683 case D3DSHADE_GOURAUD:
1684 glShadeModel(GL_SMOOTH);
1685 checkGLcall("glShadeModel");
1687 case D3DSHADE_PHONG:
1688 FIXME("D3DSHADE_PHONG isn't supported?\n");
1691 return D3DERR_INVALIDCALL;
1693 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
1697 case D3DRS_DITHERENABLE :
1699 glEnable(GL_DITHER);
1700 checkGLcall("glEnable GL_DITHER");
1702 glDisable(GL_DITHER);
1703 checkGLcall("glDisable GL_DITHER");
1707 case D3DRS_ZWRITEENABLE :
1710 checkGLcall("glDepthMask");
1713 checkGLcall("glDepthMask");
1719 int glParm = GL_LESS;
1721 switch ((D3DCMPFUNC) Value) {
1722 case D3DCMP_NEVER: glParm=GL_NEVER; break;
1723 case D3DCMP_LESS: glParm=GL_LESS; break;
1724 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
1725 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
1726 case D3DCMP_GREATER: glParm=GL_GREATER; break;
1727 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
1728 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
1729 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
1731 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1733 glDepthFunc(glParm);
1734 checkGLcall("glDepthFunc");
1738 case D3DRS_AMBIENT :
1741 D3DCOLORTOGLFLOAT4(Value, col);
1742 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
1743 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
1744 checkGLcall("glLightModel for MODEL_AMBIENT");
1749 case D3DRS_ALPHABLENDENABLE :
1752 checkGLcall("glEnable GL_BLEND");
1754 glDisable(GL_BLEND);
1755 checkGLcall("glDisable GL_BLEND");
1759 case D3DRS_SRCBLEND :
1760 case D3DRS_DESTBLEND :
1762 int newVal = GL_ZERO;
1764 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
1765 case D3DBLEND_ONE : newVal = GL_ONE; break;
1766 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
1767 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
1768 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
1769 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
1770 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
1771 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
1772 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
1773 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
1774 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
1776 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
1777 This->srcBlend = newVal;
1778 This->dstBlend = newVal;
1781 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
1782 This->srcBlend = newVal;
1783 This->dstBlend = newVal;
1786 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
1789 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
1790 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
1791 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
1792 glBlendFunc(This->srcBlend, This->dstBlend);
1794 checkGLcall("glBlendFunc");
1798 case D3DRS_ALPHATESTENABLE :
1800 glEnable(GL_ALPHA_TEST);
1801 checkGLcall("glEnable GL_ALPHA_TEST");
1803 glDisable(GL_ALPHA_TEST);
1804 checkGLcall("glDisable GL_ALPHA_TEST");
1808 case D3DRS_ALPHAFUNC :
1810 int glParm = GL_LESS;
1811 float ref = ((float) This->stateBlock->renderState[D3DRS_ALPHAREF]) / 255.0f;
1813 switch ((D3DCMPFUNC) Value) {
1814 case D3DCMP_NEVER: glParm = GL_NEVER; break;
1815 case D3DCMP_LESS: glParm = GL_LESS; break;
1816 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
1817 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
1818 case D3DCMP_GREATER: glParm = GL_GREATER; break;
1819 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
1820 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
1821 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
1823 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1825 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
1826 glAlphaFunc(glParm, ref);
1827 This->alphafunc = glParm;
1828 checkGLcall("glAlphaFunc");
1832 case D3DRS_ALPHAREF :
1834 int glParm = This->alphafunc;
1837 ref = ((float) Value) / 255.0f;
1838 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
1839 glAlphaFunc(glParm, ref);
1840 checkGLcall("glAlphaFunc");
1844 case D3DRS_CLIPPLANEENABLE :
1845 case D3DRS_CLIPPING :
1847 /* Ensure we only do the changed clip planes */
1848 DWORD enable = 0xFFFFFFFF;
1849 DWORD disable = 0x00000000;
1851 /* If enabling / disabling all */
1852 if (State == D3DRS_CLIPPING) {
1854 enable = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
1857 disable = This->stateBlock->renderState[D3DRS_CLIPPLANEENABLE];
1861 enable = Value & ~OldValue;
1862 disable = ~Value & OldValue;
1865 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
1866 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
1867 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
1868 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
1869 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
1870 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
1872 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
1873 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
1874 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
1875 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
1876 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
1877 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
1879 /** update clipping status */
1881 This->stateBlock->clip_status.ClipUnion = 0;
1882 This->stateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
1884 This->stateBlock->clip_status.ClipUnion = 0;
1885 This->stateBlock->clip_status.ClipIntersection = 0;
1890 case D3DRS_BLENDOP :
1892 int glParm = GL_FUNC_ADD;
1894 switch ((D3DBLENDOP) Value) {
1895 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
1896 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
1897 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
1898 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
1899 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
1901 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
1903 TRACE("glBlendEquation(%x)\n", glParm);
1904 glBlendEquation(glParm);
1905 checkGLcall("glBlendEquation");
1909 case D3DRS_TEXTUREFACTOR :
1913 /* Note the texture color applies to all textures whereas
1914 GL_TEXTURE_ENV_COLOR applies to active only */
1916 D3DCOLORTOGLFLOAT4(Value, col);
1917 /* Set the default alpha blend color */
1918 glBlendColor(col[0], col[1], col[2], col[3]);
1919 checkGLcall("glBlendColor");
1921 /* And now the default texture color as well */
1922 for (i = 0; i < GL_LIMITS(textures); i++) {
1924 /* Note the D3DRS value applies to all textures, but GL has one
1925 per texture, so apply it now ready to be used! */
1926 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
1929 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
1932 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
1933 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
1938 case D3DRS_SPECULARENABLE :
1940 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
1941 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
1942 specular color. This is wrong:
1943 Separate specular color means the specular colour is maintained separately, whereas
1944 single color means it is merged in. However in both cases they are being used to
1946 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
1947 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
1951 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->updateStateBlock->material.Specular);
1952 checkGLcall("glMaterialfv");
1953 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1954 glEnable(GL_COLOR_SUM_EXT);
1956 TRACE("Specular colors cannot be enabled in this version of opengl\n");
1958 checkGLcall("glEnable(GL_COLOR_SUM)");
1960 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1962 /* for the case of enabled lighting: */
1963 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1964 checkGLcall("glMaterialfv");
1966 /* for the case of disabled lighting: */
1967 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
1968 glDisable(GL_COLOR_SUM_EXT);
1970 TRACE("Specular colors cannot be disabled in this version of opengl\n");
1972 checkGLcall("glDisable(GL_COLOR_SUM)");
1977 case D3DRS_STENCILENABLE :
1979 glEnable(GL_STENCIL_TEST);
1980 checkGLcall("glEnable GL_STENCIL_TEST");
1982 glDisable(GL_STENCIL_TEST);
1983 checkGLcall("glDisable GL_STENCIL_TEST");
1987 case D3DRS_STENCILFUNC :
1989 int glParm = GL_ALWAYS;
1990 int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
1991 GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
1993 switch ((D3DCMPFUNC) Value) {
1994 case D3DCMP_NEVER: glParm=GL_NEVER; break;
1995 case D3DCMP_LESS: glParm=GL_LESS; break;
1996 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
1997 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
1998 case D3DCMP_GREATER: glParm=GL_GREATER; break;
1999 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2000 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2001 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2003 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2005 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2006 This->stencilfunc = glParm;
2007 glStencilFunc(glParm, ref, mask);
2008 checkGLcall("glStencilFunc");
2012 case D3DRS_STENCILREF :
2014 int glParm = This->stencilfunc;
2016 GLuint mask = This->stateBlock->renderState[D3DRS_STENCILMASK];
2019 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2020 glStencilFunc(glParm, ref, mask);
2021 checkGLcall("glStencilFunc");
2025 case D3DRS_STENCILMASK :
2027 int glParm = This->stencilfunc;
2028 int ref = This->stateBlock->renderState[D3DRS_STENCILREF];
2029 GLuint mask = Value;
2031 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2032 glStencilFunc(glParm, ref, mask);
2033 checkGLcall("glStencilFunc");
2037 case D3DRS_STENCILFAIL :
2043 fail = StencilOp(Value);
2044 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2045 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2046 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2047 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2049 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2050 glStencilOp(fail, zfail, zpass);
2051 checkGLcall("glStencilOp(fail, zfail, zpass);");
2054 case D3DRS_STENCILZFAIL :
2060 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2061 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2062 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2063 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2064 zfail = StencilOp(Value);
2066 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2067 glStencilOp(fail, zfail, zpass);
2068 checkGLcall("glStencilOp(fail, zfail, zpass);");
2071 case D3DRS_STENCILPASS :
2077 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2078 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2079 zpass = StencilOp(Value);
2080 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2081 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2083 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2084 glStencilOp(fail, zfail, zpass);
2085 checkGLcall("glStencilOp(fail, zfail, zpass);");
2089 case D3DRS_STENCILWRITEMASK :
2091 glStencilMask(Value);
2092 TRACE("glStencilMask(%lu)\n", Value);
2093 checkGLcall("glStencilMask");
2097 case D3DRS_FOGENABLE :
2099 if (Value/* && This->stateBlock->renderState[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2101 checkGLcall("glEnable GL_FOG");
2104 checkGLcall("glDisable GL_FOG");
2109 case D3DRS_RANGEFOGENABLE :
2112 TRACE("Enabled RANGEFOG");
2114 TRACE("Disabled RANGEFOG");
2119 case D3DRS_FOGCOLOR :
2122 D3DCOLORTOGLFLOAT4(Value, col);
2123 /* Set the default alpha blend color */
2124 glFogfv(GL_FOG_COLOR, &col[0]);
2125 checkGLcall("glFog GL_FOG_COLOR");
2129 case D3DRS_FOGTABLEMODE :
2131 glHint(GL_FOG_HINT, GL_NICEST);
2133 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2134 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2135 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2136 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2138 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2140 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2141 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2146 case D3DRS_FOGVERTEXMODE :
2148 glHint(GL_FOG_HINT, GL_FASTEST);
2150 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2151 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2152 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2153 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2155 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2157 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2158 glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2163 case D3DRS_FOGSTART :
2166 glFogfv(GL_FOG_START, &tmpvalue.f);
2167 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2168 TRACE("Fog Start == %f\n", tmpvalue.f);
2175 glFogfv(GL_FOG_END, &tmpvalue.f);
2176 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2177 TRACE("Fog End == %f\n", tmpvalue.f);
2181 case D3DRS_FOGDENSITY :
2184 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2185 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2189 case D3DRS_VERTEXBLEND :
2191 This->updateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2192 TRACE("Vertex Blending state to %ld\n", Value);
2196 case D3DRS_TWEENFACTOR :
2199 This->updateStateBlock->tween_factor = tmpvalue.f;
2200 TRACE("Vertex Blending Tween Factor to %f\n", This->updateStateBlock->tween_factor);
2204 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2206 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2210 case D3DRS_COLORVERTEX :
2211 case D3DRS_DIFFUSEMATERIALSOURCE :
2212 case D3DRS_SPECULARMATERIALSOURCE :
2213 case D3DRS_AMBIENTMATERIALSOURCE :
2214 case D3DRS_EMISSIVEMATERIALSOURCE :
2216 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2218 if (This->stateBlock->renderState[D3DRS_COLORVERTEX]) {
2219 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2220 This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE],
2221 This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE],
2222 This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE],
2223 This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE]);
2225 if (This->stateBlock->renderState[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2226 if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2227 Parm = GL_AMBIENT_AND_DIFFUSE;
2231 } else if (This->stateBlock->renderState[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2233 } else if (This->stateBlock->renderState[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2235 } else if (This->stateBlock->renderState[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2242 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2244 This->tracking_color = NEEDS_TRACKING;
2245 This->tracking_parm = Parm;
2249 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2254 case D3DRS_LINEPATTERN :
2260 tmppattern.d = Value;
2262 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2264 if (tmppattern.lp.wRepeatFactor) {
2265 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2266 checkGLcall("glLineStipple(repeat, linepattern)");
2267 glEnable(GL_LINE_STIPPLE);
2268 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2270 glDisable(GL_LINE_STIPPLE);
2271 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2280 TRACE("ZBias value %f\n", tmpvalue.f);
2281 glPolygonOffset(0, -tmpvalue.f);
2282 checkGLcall("glPolygonOffset(0, -Value)");
2283 glEnable(GL_POLYGON_OFFSET_FILL);
2284 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2285 glEnable(GL_POLYGON_OFFSET_LINE);
2286 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2287 glEnable(GL_POLYGON_OFFSET_POINT);
2288 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2290 glDisable(GL_POLYGON_OFFSET_FILL);
2291 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2292 glDisable(GL_POLYGON_OFFSET_LINE);
2293 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2294 glDisable(GL_POLYGON_OFFSET_POINT);
2295 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2300 case D3DRS_NORMALIZENORMALS :
2302 glEnable(GL_NORMALIZE);
2303 checkGLcall("glEnable(GL_NORMALIZE);");
2305 glDisable(GL_NORMALIZE);
2306 checkGLcall("glDisable(GL_NORMALIZE);");
2310 case D3DRS_POINTSIZE :
2312 TRACE("Set point size to %f\n", tmpvalue.f);
2313 glPointSize(tmpvalue.f);
2314 checkGLcall("glPointSize(...);");
2317 case D3DRS_POINTSIZE_MIN :
2318 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2320 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2321 checkGLcall("glPointParameterfEXT(...);");
2323 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2327 case D3DRS_POINTSIZE_MAX :
2328 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2330 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2331 checkGLcall("glPointParameterfEXT(...);");
2333 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2337 case D3DRS_POINTSCALE_A :
2338 case D3DRS_POINTSCALE_B :
2339 case D3DRS_POINTSCALE_C :
2340 case D3DRS_POINTSCALEENABLE :
2342 /* If enabled, supply the parameters, otherwise fall back to defaults */
2343 if (This->stateBlock->renderState[D3DRS_POINTSCALEENABLE]) {
2344 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2345 att[0] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_A]);
2346 att[1] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_B]);
2347 att[2] = *((float*)&This->stateBlock->renderState[D3DRS_POINTSCALE_C]);
2349 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2350 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2351 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2353 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2356 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2357 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2358 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2359 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2361 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2367 case D3DRS_COLORWRITEENABLE :
2369 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2370 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2371 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2372 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2373 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2374 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2375 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2376 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2377 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2378 checkGLcall("glColorMask(...)");
2382 case D3DRS_LOCALVIEWER :
2384 GLint state = (Value) ? 1 : 0;
2385 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
2386 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
2390 case D3DRS_LASTPIXEL :
2393 TRACE("Last Pixel Drawing Enabled\n");
2395 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
2400 case D3DRS_SOFTWAREVERTEXPROCESSING :
2403 TRACE("Software Processing Enabled\n");
2405 TRACE("Software Processing Disabled\n");
2410 /** not supported */
2411 case D3DRS_ZVISIBLE :
2414 return D3DERR_INVALIDCALL;
2417 /* Unhandled yet...! */
2418 case D3DRS_EDGEANTIALIAS :
2427 case D3DRS_POINTSPRITEENABLE :
2428 case D3DRS_MULTISAMPLEANTIALIAS :
2429 case D3DRS_MULTISAMPLEMASK :
2430 case D3DRS_PATCHEDGESTYLE :
2431 case D3DRS_PATCHSEGMENTS :
2432 case D3DRS_DEBUGMONITORTOKEN :
2433 case D3DRS_POSITIONORDER :
2434 case D3DRS_NORMALORDER :
2435 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2436 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2439 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2447 HRESULT WINAPI IWineD3DDeviceImpl_GetRenderState(IWineD3DDevice *iface, D3DRENDERSTATETYPE State, DWORD *pValue) {
2448 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2449 TRACE("(%p) for State %d = %ld\n", This, State, This->stateBlock->renderState[State]);
2450 *pValue = This->stateBlock->renderState[State];
2456 * Get / Set Texture Stage States
2457 * TODO: Verify against dx9 definitions
2459 HRESULT WINAPI IWineD3DDeviceImpl_SetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
2460 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2466 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
2468 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
2470 /* Reject invalid texture units */
2471 if (Stage >= GL_LIMITS(textures)) {
2472 TRACE("Attempt to access invalid texture rejected\n");
2473 return D3DERR_INVALIDCALL;
2476 This->updateStateBlock->changed.textureState[Stage][Type] = TRUE;
2477 This->updateStateBlock->set.textureState[Stage][Type] = TRUE;
2478 This->updateStateBlock->textureState[Stage][Type] = Value;
2480 /* Handle recording of state blocks */
2481 if (This->isRecordingState) {
2482 TRACE("Recording... not performing anything\n");
2488 /* Make appropriate texture active */
2489 VTRACE(("Activating appropriate texture state %ld\n", Stage));
2490 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2491 GLACTIVETEXTURE(Stage);
2492 } else if (Stage > 0) {
2493 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2498 case D3DTSS_MINFILTER :
2499 case D3DTSS_MIPFILTER :
2501 DWORD ValueMIN = This->stateBlock->textureState[Stage][D3DTSS_MINFILTER];
2502 DWORD ValueMIP = This->stateBlock->textureState[Stage][D3DTSS_MIPFILTER];
2503 GLint realVal = GL_LINEAR;
2505 if (ValueMIN == D3DTEXF_NONE) {
2506 /* Doesn't really make sense - Windows just seems to disable
2507 mipmapping when this occurs */
2508 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
2509 realVal = GL_LINEAR;
2510 } else if (ValueMIN == D3DTEXF_POINT) {
2512 if (ValueMIP == D3DTEXF_NONE) {
2513 realVal = GL_NEAREST;
2514 } else if (ValueMIP == D3DTEXF_POINT) {
2515 realVal = GL_NEAREST_MIPMAP_NEAREST;
2516 } else if (ValueMIP == D3DTEXF_LINEAR) {
2517 realVal = GL_NEAREST_MIPMAP_LINEAR;
2519 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2520 realVal = GL_NEAREST;
2522 } else if (ValueMIN == D3DTEXF_LINEAR) {
2524 if (ValueMIP == D3DTEXF_NONE) {
2525 realVal = GL_LINEAR;
2526 } else if (ValueMIP == D3DTEXF_POINT) {
2527 realVal = GL_LINEAR_MIPMAP_NEAREST;
2528 } else if (ValueMIP == D3DTEXF_LINEAR) {
2529 realVal = GL_LINEAR_MIPMAP_LINEAR;
2531 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2532 realVal = GL_LINEAR;
2534 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
2535 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2536 if (ValueMIP == D3DTEXF_NONE) {
2537 realVal = GL_LINEAR_MIPMAP_LINEAR;
2538 } else if (ValueMIP == D3DTEXF_POINT) {
2539 realVal = GL_LINEAR_MIPMAP_NEAREST;
2540 } else if (ValueMIP == D3DTEXF_LINEAR) {
2541 realVal = GL_LINEAR_MIPMAP_LINEAR;
2543 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2544 realVal = GL_LINEAR;
2547 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
2548 realVal = GL_LINEAR;
2551 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
2552 realVal = GL_LINEAR_MIPMAP_LINEAR;
2555 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
2556 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
2557 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
2559 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
2561 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
2562 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2563 GL_TEXTURE_MAX_ANISOTROPY_EXT,
2564 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2565 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
2570 case D3DTSS_MAGFILTER :
2572 DWORD ValueMAG = This->stateBlock->textureState[Stage][D3DTSS_MAGFILTER];
2573 GLint realVal = GL_NEAREST;
2575 if (ValueMAG == D3DTEXF_POINT) {
2576 realVal = GL_NEAREST;
2577 } else if (ValueMAG == D3DTEXF_LINEAR) {
2578 realVal = GL_LINEAR;
2579 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
2580 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2581 realVal = GL_LINEAR;
2583 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
2584 realVal = GL_NEAREST;
2587 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
2588 realVal = GL_NEAREST;
2590 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
2591 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
2592 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
2594 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
2596 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
2597 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2598 GL_TEXTURE_MAX_ANISOTROPY_EXT,
2599 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2600 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
2605 case D3DTSS_MAXMIPLEVEL :
2608 * Not really the same, but the more apprioprate than nothing
2610 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2611 GL_TEXTURE_BASE_LEVEL,
2612 This->stateBlock->textureState[Stage][D3DTSS_MAXMIPLEVEL]);
2613 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
2617 case D3DTSS_MAXANISOTROPY :
2619 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2620 glTexParameteri(This->stateBlock->textureDimensions[Stage],
2621 GL_TEXTURE_MAX_ANISOTROPY_EXT,
2622 This->stateBlock->textureState[Stage][D3DTSS_MAXANISOTROPY]);
2623 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
2628 case D3DTSS_MIPMAPLODBIAS :
2630 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
2632 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
2633 GL_TEXTURE_LOD_BIAS_EXT,
2635 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
2640 case D3DTSS_ALPHAOP :
2641 case D3DTSS_COLOROP :
2644 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
2645 /* TODO: Disable by making this and all later levels disabled */
2646 glDisable(GL_TEXTURE_1D);
2647 checkGLcall("Disable GL_TEXTURE_1D");
2648 glDisable(GL_TEXTURE_2D);
2649 checkGLcall("Disable GL_TEXTURE_2D");
2650 glDisable(GL_TEXTURE_3D);
2651 checkGLcall("Disable GL_TEXTURE_3D");
2652 break; /* Don't bother setting the texture operations */
2654 /* Enable only the appropriate texture dimension */
2655 if (Type == D3DTSS_COLOROP) {
2656 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2657 glEnable(GL_TEXTURE_1D);
2658 checkGLcall("Enable GL_TEXTURE_1D");
2660 glDisable(GL_TEXTURE_1D);
2661 checkGLcall("Disable GL_TEXTURE_1D");
2663 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
2664 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
2665 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
2666 checkGLcall("Enable GL_TEXTURE_2D");
2668 glEnable(GL_TEXTURE_2D);
2669 checkGLcall("Enable GL_TEXTURE_2D");
2672 glDisable(GL_TEXTURE_2D);
2673 checkGLcall("Disable GL_TEXTURE_2D");
2675 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
2676 glEnable(GL_TEXTURE_3D);
2677 checkGLcall("Enable GL_TEXTURE_3D");
2679 glDisable(GL_TEXTURE_3D);
2680 checkGLcall("Disable GL_TEXTURE_3D");
2682 if (This->stateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
2683 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
2684 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
2686 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2687 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
2691 /* Drop through... (Except disable case) */
2692 case D3DTSS_COLORARG0 :
2693 case D3DTSS_COLORARG1 :
2694 case D3DTSS_COLORARG2 :
2695 case D3DTSS_ALPHAARG0 :
2696 case D3DTSS_ALPHAARG1 :
2697 case D3DTSS_ALPHAARG2 :
2699 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
2700 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
2702 set_tex_op(iface, TRUE, Stage, This->stateBlock->textureState[Stage][D3DTSS_ALPHAOP],
2703 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG1],
2704 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG2],
2705 This->stateBlock->textureState[Stage][D3DTSS_ALPHAARG0]);
2707 set_tex_op(iface, FALSE, Stage, This->stateBlock->textureState[Stage][D3DTSS_COLOROP],
2708 This->stateBlock->textureState[Stage][D3DTSS_COLORARG1],
2709 This->stateBlock->textureState[Stage][D3DTSS_COLORARG2],
2710 This->stateBlock->textureState[Stage][D3DTSS_COLORARG0]);
2716 case D3DTSS_ADDRESSU :
2717 case D3DTSS_ADDRESSV :
2718 case D3DTSS_ADDRESSW :
2720 GLint wrapParm = GL_REPEAT;
2723 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
2724 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
2725 case D3DTADDRESS_BORDER:
2727 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
2728 wrapParm = GL_CLAMP_TO_BORDER_ARB;
2730 /* FIXME: Not right, but better */
2731 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
2732 wrapParm = GL_REPEAT;
2736 case D3DTADDRESS_MIRROR:
2738 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
2739 wrapParm = GL_MIRRORED_REPEAT_ARB;
2741 /* Unsupported in OpenGL pre-1.4 */
2742 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
2743 wrapParm = GL_REPEAT;
2747 case D3DTADDRESS_MIRRORONCE:
2749 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
2750 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
2752 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
2753 wrapParm = GL_REPEAT;
2759 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
2760 wrapParm = GL_REPEAT;
2764 case D3DTSS_ADDRESSU:
2765 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2766 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
2767 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
2769 case D3DTSS_ADDRESSV:
2770 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2771 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
2772 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
2774 case D3DTSS_ADDRESSW:
2775 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->stateBlock->textureDimensions[Stage]);
2776 glTexParameteri(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
2777 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
2780 break; /** stupic compilator */
2785 case D3DTSS_BORDERCOLOR :
2788 D3DCOLORTOGLFLOAT4(Value, col);
2789 TRACE("Setting border color for %x to %lx\n", This->stateBlock->textureDimensions[Stage], Value);
2790 glTexParameterfv(This->stateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
2791 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
2795 case D3DTSS_TEXCOORDINDEX :
2797 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
2799 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
2800 one flag, you can still specify an index value, which the system uses to
2801 determine the texture wrapping mode.
2802 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
2803 means use the vertex position (camera-space) as the input texture coordinates
2804 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
2805 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
2806 to the TEXCOORDINDEX value */
2809 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
2811 switch (Value & 0xFFFF0000) {
2812 case D3DTSS_TCI_PASSTHRU:
2813 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
2814 glDisable(GL_TEXTURE_GEN_S);
2815 glDisable(GL_TEXTURE_GEN_T);
2816 glDisable(GL_TEXTURE_GEN_R);
2817 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
2820 case D3DTSS_TCI_CAMERASPACEPOSITION:
2821 /* CameraSpacePosition means use the vertex position, transformed to camera space,
2822 as the input texture coordinates for this stage's texture transformation. This
2823 equates roughly to EYE_LINEAR */
2825 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2826 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2827 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2828 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2829 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2831 glMatrixMode(GL_MODELVIEW);
2834 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2835 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2836 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2837 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2840 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
2841 glEnable(GL_TEXTURE_GEN_S);
2842 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2843 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2844 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2845 glEnable(GL_TEXTURE_GEN_T);
2846 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2847 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2848 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2849 glEnable(GL_TEXTURE_GEN_R);
2850 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2851 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
2852 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
2856 case D3DTSS_TCI_CAMERASPACENORMAL:
2858 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2859 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2860 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2861 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2862 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2863 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2865 glMatrixMode(GL_MODELVIEW);
2868 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2869 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2870 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2871 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2874 glEnable(GL_TEXTURE_GEN_S);
2875 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2876 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2877 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2878 glEnable(GL_TEXTURE_GEN_T);
2879 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2880 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2881 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2882 glEnable(GL_TEXTURE_GEN_R);
2883 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2884 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
2885 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
2890 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
2892 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
2893 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
2894 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
2895 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
2896 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
2897 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
2899 glMatrixMode(GL_MODELVIEW);
2902 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
2903 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
2904 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
2905 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
2908 glEnable(GL_TEXTURE_GEN_S);
2909 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
2910 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2911 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2912 glEnable(GL_TEXTURE_GEN_T);
2913 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
2914 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2915 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2916 glEnable(GL_TEXTURE_GEN_R);
2917 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
2918 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
2919 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
2924 /* Unhandled types: */
2927 /* ? disable GL_TEXTURE_GEN_n ? */
2928 glDisable(GL_TEXTURE_GEN_S);
2929 glDisable(GL_TEXTURE_GEN_T);
2930 glDisable(GL_TEXTURE_GEN_R);
2931 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
2938 case D3DTSS_TEXTURETRANSFORMFLAGS :
2939 set_texture_matrix((float *)&This->stateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
2942 case D3DTSS_BUMPENVMAT00 :
2943 case D3DTSS_BUMPENVMAT01 :
2944 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
2946 case D3DTSS_BUMPENVMAT10 :
2947 case D3DTSS_BUMPENVMAT11 :
2948 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
2951 case D3DTSS_BUMPENVLSCALE :
2952 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2955 case D3DTSS_BUMPENVLOFFSET :
2956 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2959 case D3DTSS_RESULTARG :
2960 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2964 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
2965 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
2973 HRESULT WINAPI IWineD3DDeviceImpl_GetTextureStageState(IWineD3DDevice *iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD* pValue) {
2974 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2975 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->updateStateBlock->textureState[Stage][Type]);
2976 *pValue = This->updateStateBlock->textureState[Stage][Type];
2981 * Scene related functions
2983 HRESULT WINAPI IWineD3DDeviceImpl_BeginScene(IWineD3DDevice *iface) {
2984 /* At the moment we have no need for any functionality at the beginning
2986 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2987 TRACE("(%p) : stub\n", This);
2991 HRESULT WINAPI IWineD3DDeviceImpl_EndScene(IWineD3DDevice *iface) {
2992 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
2993 TRACE("(%p)\n", This);
2998 checkGLcall("glFlush");
3000 if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
3002 /* If we are rendering to a texture (surface) then flag it as dirty.
3003 A surfaces container is either the appropriate texture or the device itself
3004 depending on how the surface was created. */
3005 if (This->renderTarget != NULL && ((IWineD3DDeviceImpl *)This->renderTarget->container != This)) {
3007 IWineD3DBaseTexture *cont = (IWineD3DBaseTexture *)This->renderTarget->container;
3008 /** always dirtify for now. we must find a better way to see that surface have been modified */
3009 This->renderTarget->inPBuffer = TRUE;
3010 This->renderTarget->inTexture = FALSE;
3011 IWineD3DBaseTexture_SetDirty(cont, TRUE);
3012 IWineD3DBaseTexture_PreLoad(cont);
3013 This->renderTarget->inPBuffer = FALSE;
3021 HRESULT WINAPI IWineD3DDeviceImpl_Present(IWineD3DDevice *iface,
3022 CONST RECT* pSourceRect, CONST RECT* pDestRect,
3023 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
3024 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3025 TRACE("(%p) Presenting the frame\n", This);
3029 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
3031 glXSwapBuffers(This->display, This->drawable);
3032 /* Don't call checkGLcall, as glGetError is not applicable here */
3034 TRACE("glXSwapBuffers called, Starting new frame\n");
3037 if (TRACE_ON(d3d_fps))
3039 static long prev_time, frames;
3041 DWORD time = GetTickCount();
3043 /* every 1.5 seconds */
3044 if (time - prev_time > 1500) {
3045 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
3051 #if defined(FRAME_DEBUGGING)
3053 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
3056 FIXME("Enabling D3D Trace\n");
3057 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
3058 #if defined(SHOW_FRAME_MAKEUP)
3059 FIXME("Singe Frame snapshots Starting\n");
3060 isDumpingFrames = TRUE;
3061 glClear(GL_COLOR_BUFFER_BIT);
3064 #if defined(SINGLE_FRAME_DEBUGGING)
3066 #if defined(SHOW_FRAME_MAKEUP)
3067 FIXME("Singe Frame snapshots Finishing\n");
3068 isDumpingFrames = FALSE;
3070 FIXME("Singe Frame trace complete\n");
3071 DeleteFileA("C:\\D3DTRACE");
3072 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3078 #if defined(SHOW_FRAME_MAKEUP)
3079 FIXME("Singe Frame snapshots Finishing\n");
3080 isDumpingFrames = FALSE;
3082 FIXME("Disabling D3D Trace\n");
3083 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
3090 /* Although this is not strictly required, a simple demo showed this does occur
3091 on (at least non-debug) d3d */
3092 if (This->presentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
3093 IWineD3DDevice_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
3099 HRESULT WINAPI IWineD3DDeviceImpl_Clear(IWineD3DDevice *iface, DWORD Count, CONST D3DRECT* pRects,
3100 DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
3101 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3103 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
3104 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
3105 when the depth-buffer format does not contain stencil buffer information, this method fails. */
3106 GLbitfield glMask = 0;
3107 GLboolean old_ztest;
3108 GLfloat old_z_clear_value;
3109 GLint old_stencil_clear_value;
3110 GLfloat old_color_clear_value[4];
3112 CONST D3DRECT* curRect;
3114 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
3115 Count, pRects, Flags, Z, Stencil);
3119 glEnable(GL_SCISSOR_TEST);
3120 checkGLcall("glEnable GL_SCISSOR_TEST");
3122 if (Count > 0 && pRects) {
3128 /* Only set the values up once, as they are not changing */
3129 if (Flags & D3DCLEAR_STENCIL) {
3130 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
3131 glClearStencil(Stencil);
3132 checkGLcall("glClearStencil");
3133 glMask = glMask | GL_STENCIL_BUFFER_BIT;
3134 glStencilMask(0xFFFFFFFF);
3137 if (Flags & D3DCLEAR_ZBUFFER) {
3138 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
3139 glDepthMask(GL_TRUE);
3140 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
3142 checkGLcall("glClearDepth");
3143 glMask = glMask | GL_DEPTH_BUFFER_BIT;
3146 if (Flags & D3DCLEAR_TARGET) {
3147 TRACE("Clearing screen with glClear to color %lx\n", Color);
3148 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
3149 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
3150 ((Color >> 8) & 0xFF) / 255.0f,
3151 ((Color >> 0) & 0xFF) / 255.0f,
3152 ((Color >> 24) & 0xFF) / 255.0f);
3153 checkGLcall("glClearColor");
3155 /* Clear ALL colors! */
3156 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
3157 glMask = glMask | GL_COLOR_BUFFER_BIT;
3160 /* Now process each rect in turn */
3161 for (i = 0; i < Count || i == 0; i++) {
3164 /* Note gl uses lower left, width/height */
3165 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
3166 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
3167 curRect->x1, (This->renderTarget->currentDesc.Height - curRect->y2),
3168 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3169 glScissor(curRect->x1, (This->renderTarget->currentDesc.Height - curRect->y2),
3170 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
3171 checkGLcall("glScissor");
3173 glScissor(This->stateBlock->viewport.X,
3174 (This->renderTarget->currentDesc.Height - (This->stateBlock->viewport.Y + This->stateBlock->viewport.Height)),
3175 This->stateBlock->viewport.Width,
3176 This->stateBlock->viewport.Height);
3177 checkGLcall("glScissor");
3180 /* Clear the selected rectangle (or full screen) */
3182 checkGLcall("glClear");
3184 /* Step to the next rectangle */
3185 if (curRect) curRect = curRect + sizeof(D3DRECT);
3188 /* Restore the old values (why..?) */
3189 if (Flags & D3DCLEAR_STENCIL) {
3190 glClearStencil(old_stencil_clear_value);
3191 glStencilMask(This->stateBlock->renderState[D3DRS_STENCILWRITEMASK]);
3193 if (Flags & D3DCLEAR_ZBUFFER) {
3194 glDepthMask(old_ztest);
3195 glClearDepth(old_z_clear_value);
3197 if (Flags & D3DCLEAR_TARGET) {
3198 glClearColor(old_color_clear_value[0],
3199 old_color_clear_value[1],
3200 old_color_clear_value[2],
3201 old_color_clear_value[3]);
3202 glColorMask(This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3203 This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3204 This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3205 This->stateBlock->renderState[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3208 glDisable(GL_SCISSOR_TEST);
3209 checkGLcall("glDisable");
3218 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitive(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex,
3219 UINT PrimitiveCount) {
3221 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3222 This->stateBlock->streamIsUP = FALSE;
3224 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType,
3225 debug_d3dprimitivetype(PrimitiveType),
3226 StartVertex, PrimitiveCount);
3227 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3232 /* TODO: baseVIndex needs to be provided from This->stateBlock->baseVertexIndex when called from d3d8 */
3233 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitive(IWineD3DDevice *iface,
3234 D3DPRIMITIVETYPE PrimitiveType,
3235 INT baseVIndex, UINT minIndex,
3236 UINT NumVertices,UINT startIndex,UINT primCount) {
3238 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3240 IWineD3DIndexBuffer *pIB;
3241 D3DINDEXBUFFER_DESC IdxBufDsc;
3243 pIB = This->stateBlock->pIndexData;
3244 This->stateBlock->streamIsUP = FALSE;
3246 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, baseVidx=%d, countP=%d \n", This,
3247 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3248 minIndex, NumVertices, startIndex, baseVIndex, primCount);
3250 IWineD3DIndexBuffer_GetDesc(pIB, &IdxBufDsc);
3251 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3257 drawPrimitive(iface, PrimitiveType, primCount, baseVIndex,
3258 startIndex, idxStride,
3259 ((IWineD3DIndexBufferImpl *) pIB)->allocatedMemory,
3265 HRESULT WINAPI IWineD3DDeviceImpl_DrawPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
3266 UINT PrimitiveCount, CONST void* pVertexStreamZeroData,
3267 UINT VertexStreamZeroStride) {
3268 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3270 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType,
3271 debug_d3dprimitivetype(PrimitiveType),
3272 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3274 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
3276 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
3277 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
3278 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
3279 This->stateBlock->streamIsUP = TRUE;
3280 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3281 This->stateBlock->stream_stride[0] = 0;
3282 This->stateBlock->stream_source[0] = NULL;
3284 /*stream zero settings set to null at end, as per the msdn */
3288 HRESULT WINAPI IWineD3DDeviceImpl_DrawIndexedPrimitiveUP(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType,
3289 UINT MinVertexIndex,
3290 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3291 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3292 UINT VertexStreamZeroStride) {
3294 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3296 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n",
3297 This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3298 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData,
3299 IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3301 if (This->stateBlock->stream_source[0] != NULL) IWineD3DVertexBuffer_Release(This->stateBlock->stream_source[0]);
3303 if (IndexDataFormat == D3DFMT_INDEX16) {
3309 /* Note in the following, it's not this type, but that's the purpose of streamIsUP */
3310 This->stateBlock->stream_source[0] = (IWineD3DVertexBuffer *)pVertexStreamZeroData;
3311 This->stateBlock->streamIsUP = TRUE;
3312 This->stateBlock->stream_stride[0] = VertexStreamZeroStride;
3314 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, idxStride, pIndexData, MinVertexIndex);
3316 /* stream zero settings set to null at end as per the msdn */
3317 This->stateBlock->stream_source[0] = NULL;
3318 This->stateBlock->stream_stride[0] = 0;
3319 IWineD3DDevice_SetIndices(iface, NULL, 0);
3324 /**********************************************************
3325 * IUnknown parts follows
3326 **********************************************************/
3328 HRESULT WINAPI IWineD3DDeviceImpl_QueryInterface(IWineD3DDevice *iface,REFIID riid,LPVOID *ppobj)
3330 return E_NOINTERFACE;
3333 ULONG WINAPI IWineD3DDeviceImpl_AddRef(IWineD3DDevice *iface) {
3334 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3335 ULONG refCount = InterlockedIncrement(&This->ref);
3337 TRACE("(%p) : AddRef increasing from %ld\n", This, refCount - 1);
3341 ULONG WINAPI IWineD3DDeviceImpl_Release(IWineD3DDevice *iface) {
3342 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
3343 ULONG refCount = InterlockedDecrement(&This->ref);
3345 TRACE("(%p) : Releasing from %ld\n", This, refCount + 1);
3348 IWineD3DStateBlock_Release((IWineD3DStateBlock *)This->stateBlock);
3349 IWineD3D_Release(This->wineD3D);
3350 HeapFree(GetProcessHeap(), 0, This);
3355 /**********************************************************
3356 * IWineD3DDevice VTbl follows
3357 **********************************************************/
3359 IWineD3DDeviceVtbl IWineD3DDevice_Vtbl =
3361 IWineD3DDeviceImpl_QueryInterface,
3362 IWineD3DDeviceImpl_AddRef,
3363 IWineD3DDeviceImpl_Release,
3364 IWineD3DDeviceImpl_GetParent,
3365 IWineD3DDeviceImpl_CreateVertexBuffer,
3366 IWineD3DDeviceImpl_CreateIndexBuffer,
3367 IWineD3DDeviceImpl_CreateStateBlock,
3368 IWineD3DDeviceImpl_CreateRenderTarget,
3369 IWineD3DDeviceImpl_CreateOffscreenPlainSurface,
3370 IWineD3DDeviceImpl_CreateTexture,
3371 IWineD3DDeviceImpl_CreateVolumeTexture,
3372 IWineD3DDeviceImpl_CreateVolume,
3373 IWineD3DDeviceImpl_CreateCubeTexture,
3375 IWineD3DDeviceImpl_SetFVF,
3376 IWineD3DDeviceImpl_GetFVF,
3377 IWineD3DDeviceImpl_SetStreamSource,
3378 IWineD3DDeviceImpl_GetStreamSource,
3379 IWineD3DDeviceImpl_SetTransform,
3380 IWineD3DDeviceImpl_GetTransform,
3381 IWineD3DDeviceImpl_MultiplyTransform,
3382 IWineD3DDeviceImpl_SetLight,
3383 IWineD3DDeviceImpl_GetLight,
3384 IWineD3DDeviceImpl_SetLightEnable,
3385 IWineD3DDeviceImpl_GetLightEnable,
3386 IWineD3DDeviceImpl_SetClipPlane,
3387 IWineD3DDeviceImpl_GetClipPlane,
3388 IWineD3DDeviceImpl_SetClipStatus,
3389 IWineD3DDeviceImpl_GetClipStatus,
3390 IWineD3DDeviceImpl_SetMaterial,
3391 IWineD3DDeviceImpl_GetMaterial,
3392 IWineD3DDeviceImpl_SetIndices,
3393 IWineD3DDeviceImpl_GetIndices,
3394 IWineD3DDeviceImpl_SetViewport,
3395 IWineD3DDeviceImpl_GetViewport,
3396 IWineD3DDeviceImpl_SetRenderState,
3397 IWineD3DDeviceImpl_GetRenderState,
3398 IWineD3DDeviceImpl_SetTextureStageState,
3399 IWineD3DDeviceImpl_GetTextureStageState,
3401 IWineD3DDeviceImpl_BeginScene,
3402 IWineD3DDeviceImpl_EndScene,
3403 IWineD3DDeviceImpl_Present,
3404 IWineD3DDeviceImpl_Clear,
3406 IWineD3DDeviceImpl_DrawPrimitive,
3407 IWineD3DDeviceImpl_DrawIndexedPrimitive,
3408 IWineD3DDeviceImpl_DrawPrimitiveUP,
3409 IWineD3DDeviceImpl_DrawIndexedPrimitiveUP,
3411 IWineD3DDeviceImpl_SetupTextureStates