Make the fixed function pipeline support multiple streams for created
[wine/dcerpc.git] / dlls / d3d8 / device.c
blobf6f76ad19d6345aa5ef3f7bef05b4c238c46fac7
1 /*
2 * IDirect3DDevice8 implementation
4 * Copyright 2002 Jason Edmeades
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include "config.h"
23 #include <math.h>
25 #define NONAMELESSUNION
26 #define NONAMELESSSTRUCT
27 #include "windef.h"
28 #include "winbase.h"
29 #include "winuser.h"
30 #include "wingdi.h"
31 #include "wine/debug.h"
33 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
34 /*#define GL_GLEXT_PROTOTYPES*/
35 /*#undef GLX_GLXEXT_LEGACY*/
36 #include "d3d8_private.h"
38 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
39 #undef GL_VERSION_1_4
41 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
42 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
44 IDirect3DVertexShaderImpl* VertexShaders[64];
45 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
46 IDirect3DPixelShaderImpl* PixelShaders[64];
48 #ifdef FRAME_DEBUGGING
49 BOOL isOn = FALSE;
50 BOOL isDumpingFrames = FALSE;
51 LONG primCounter = 0;
52 #endif
55 * Utility functions or macros
57 #define conv_mat(mat,gl_mat) \
58 do { \
59 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
60 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
61 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
62 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
63 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
64 } while (0)
66 /* Apply the current values to the specified texture stage */
67 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage) {
68 ICOM_THIS(IDirect3DDevice8Impl,iface);
69 int i = 0;
70 float col[4];
72 /* Make appropriate texture active */
73 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
74 #if defined(GL_VERSION_1_3)
75 glActiveTexture(GL_TEXTURE0 + Stage);
76 #else
77 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
78 #endif
79 checkGLcall("glActiveTextureARB");
80 } else if (Stage > 0) {
81 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
84 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
85 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
86 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
89 /* Note the D3DRS value applies to all textures, but GL has one
90 * per texture, so apply it now ready to be used!
92 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
93 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
94 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
96 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
99 /* IDirect3D IUnknown parts follow: */
100 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
102 ICOM_THIS(IDirect3DDevice8Impl,iface);
104 if (IsEqualGUID(riid, &IID_IUnknown)
105 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
106 IDirect3DDevice8Impl_AddRef(iface);
107 *ppobj = This;
108 return D3D_OK;
111 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
112 return E_NOINTERFACE;
115 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
116 ICOM_THIS(IDirect3DDevice8Impl,iface);
117 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
118 return ++(This->ref);
121 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
122 ICOM_THIS(IDirect3DDevice8Impl,iface);
123 ULONG ref = --This->ref;
124 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
125 if (ref == 0) {
126 IDirect3DDevice8Impl_CleanRender(iface);
127 HeapFree(GetProcessHeap(), 0, This);
129 return ref;
132 /* IDirect3DDevice Interface follow: */
133 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
134 ICOM_THIS(IDirect3DDevice8Impl,iface);
135 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
136 return D3D_OK;
139 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
140 ICOM_THIS(IDirect3DDevice8Impl,iface);
141 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
143 * pretend we have 32MB of any type of memory queried.
145 return (1024*1024*32);
148 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
149 ICOM_THIS(IDirect3DDevice8Impl,iface);
150 FIXME("(%p) : stub\n", This); return D3D_OK;
152 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
153 ICOM_THIS(IDirect3DDevice8Impl,iface);
154 TRACE("(%p) : returning %p\n", This, This->direct3d8);
156 /* Inc ref count */
157 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
159 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
160 return D3D_OK;
162 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
163 ICOM_THIS(IDirect3DDevice8Impl,iface);
164 FIXME("(%p) : stub, calling idirect3d for now\n", This);
165 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
166 return D3D_OK;
168 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
170 HDC hdc;
171 int bpp = 0;
173 ICOM_THIS(IDirect3DDevice8Impl,iface);
174 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
175 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
176 pMode->RefreshRate = 85; /*FIXME: How to identify? */
178 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
179 bpp = GetDeviceCaps(hdc, BITSPIXEL);
180 DeleteDC(hdc);
182 switch (bpp) {
183 case 8: pMode->Format = D3DFMT_R8G8B8; break;
184 case 16: pMode->Format = D3DFMT_R5G6B5; break;
185 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
186 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
187 default:
188 FIXME("Unrecognized display mode format\n");
189 pMode->Format = D3DFMT_UNKNOWN;
192 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
193 pMode->Format, debug_d3dformat(pMode->Format));
194 return D3D_OK;
196 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
197 ICOM_THIS(IDirect3DDevice8Impl,iface);
198 TRACE("(%p) copying to %p\n", This, pParameters);
199 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
200 return D3D_OK;
202 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
203 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
204 ICOM_THIS(IDirect3DDevice8Impl,iface);
205 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
207 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
208 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
209 return D3DERR_INVALIDCALL;
211 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
212 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
213 return D3DERR_INVALIDCALL;
216 This->xHotSpot = XHotSpot;
217 This->yHotSpot = YHotSpot;
218 return D3D_OK;
220 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
221 ICOM_THIS(IDirect3DDevice8Impl,iface);
222 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
223 This->xScreenSpace = XScreenSpace;
224 This->yScreenSpace = YScreenSpace;
225 return;
227 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
228 ICOM_THIS(IDirect3DDevice8Impl,iface);
229 TRACE("(%p) : visible(%d)\n", This, bShow);
230 This->bCursorVisible = bShow;
231 return D3D_OK;
233 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
234 IDirect3DSwapChain8Impl* object;
235 ICOM_THIS(IDirect3DDevice8Impl,iface);
236 FIXME("(%p) : stub\n", This);
238 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
239 if (NULL == object) {
240 return D3DERR_OUTOFVIDEOMEMORY;
242 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
243 object->ref = 1;
245 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
246 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
247 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
249 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
250 (pPresentationParameters->BackBufferHeight == 0))) {
251 RECT Rect;
253 GetClientRect(This->win_handle, &Rect);
255 if (pPresentationParameters->BackBufferWidth == 0) {
256 pPresentationParameters->BackBufferWidth = Rect.right;
257 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
259 if (pPresentationParameters->BackBufferHeight == 0) {
260 pPresentationParameters->BackBufferHeight = Rect.bottom;
261 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
265 /* Save the presentation parms now filled in correctly */
266 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
268 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
269 pPresentationParameters->BackBufferWidth,
270 pPresentationParameters->BackBufferHeight,
271 pPresentationParameters->BackBufferFormat,
272 pPresentationParameters->MultiSampleType,
273 TRUE,
274 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
276 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
277 pPresentationParameters->BackBufferWidth,
278 pPresentationParameters->BackBufferHeight,
279 pPresentationParameters->BackBufferFormat,
280 pPresentationParameters->MultiSampleType,
281 TRUE,
282 (LPDIRECT3DSURFACE8*) &object->backBuffer);
284 if (pPresentationParameters->EnableAutoDepthStencil) {
285 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
286 pPresentationParameters->BackBufferWidth,
287 pPresentationParameters->BackBufferHeight,
288 pPresentationParameters->AutoDepthStencilFormat,
289 D3DMULTISAMPLE_NONE,
290 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
291 } else {
292 object->depthStencilBuffer = NULL;
295 *pSwapChain = (IDirect3DSwapChain8*) object;
296 return D3D_OK;
298 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
299 ICOM_THIS(IDirect3DDevice8Impl,iface);
300 FIXME("(%p) : stub\n", This); return D3D_OK;
302 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
303 ICOM_THIS(IDirect3DDevice8Impl,iface);
304 TRACE("(%p) : complete stub!\n", This);
306 ENTER_GL();
308 glXSwapBuffers(This->display, This->drawable);
309 /* Dont call checkGLcall, as glGetError is not applicable here */
310 TRACE("glXSwapBuffers called, Starting new frame\n");
312 #if defined(FRAME_DEBUGGING)
314 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
315 if (!isOn) {
316 isOn = TRUE;
317 FIXME("Enabling D3D Trace\n");
318 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
319 #if defined(SHOW_FRAME_MAKEUP)
320 FIXME("Singe Frame snapshots Starting\n");
321 isDumpingFrames = TRUE;
322 glClear(GL_COLOR_BUFFER_BIT);
323 #endif
325 #if defined(SINGLE_FRAME_DEBUGGING)
326 } else {
327 #if defined(SHOW_FRAME_MAKEUP)
328 FIXME("Singe Frame snapshots Finishing\n");
329 isDumpingFrames = FALSE;
330 #endif
331 FIXME("Singe Frame trace complete\n");
332 DeleteFileA("C:\\D3DTRACE");
333 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
334 #endif
336 } else {
337 if (isOn) {
338 isOn = FALSE;
339 #if defined(SHOW_FRAME_MAKEUP)
340 FIXME("Singe Frame snapshots Finishing\n");
341 isDumpingFrames = FALSE;
342 #endif
343 FIXME("Disabling D3D Trace\n");
344 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
348 #endif
350 LEAVE_GL();
352 return D3D_OK;
354 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
355 ICOM_THIS(IDirect3DDevice8Impl,iface);
356 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
357 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
359 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
360 FIXME("Only one backBuffer currently supported\n");
361 return D3DERR_INVALIDCALL;
364 /* Note inc ref on returned surface */
365 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
367 return D3D_OK;
369 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
370 ICOM_THIS(IDirect3DDevice8Impl,iface);
371 FIXME("(%p) : stub\n", This);
372 return D3D_OK;
374 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
375 HDC hDC;
376 ICOM_THIS(IDirect3DDevice8Impl,iface);
378 FIXME("(%p) : pRamp@%p\n", This, pRamp);
379 hDC = GetDC(This->win_handle);
380 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
381 ReleaseDC(This->win_handle, hDC);
382 return;
384 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
385 HDC hDC;
386 ICOM_THIS(IDirect3DDevice8Impl,iface);
388 FIXME("(%p) : pRamp@%p\n", This, pRamp);
389 hDC = GetDC(This->win_handle);
390 GetDeviceGammaRamp(hDC, pRamp);
391 ReleaseDC(This->win_handle, hDC);
392 return;
394 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
395 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
396 IDirect3DTexture8Impl *object;
397 int i;
398 UINT tmpW;
399 UINT tmpH;
401 ICOM_THIS(IDirect3DDevice8Impl,iface);
403 /* Allocate the storage for the device */
404 TRACE("(%p) : W(%d) H(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, debug_d3dformat(Format), Pool);
405 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
406 object->lpVtbl = &Direct3DTexture8_Vtbl;
407 object->Device = This;
408 object->ResourceType = D3DRTYPE_TEXTURE;
409 object->ref = 1;
410 object->width = Width;
411 object->height = Height;
412 object->levels = Levels;
413 object->usage = Usage;
414 object->format = Format;
416 /* Calculate levels for mip mapping */
417 if (Levels == 0) {
418 object->levels++;
419 tmpW = Width;
420 tmpH = Height;
421 while (tmpW > 1 && tmpH > 1) {
422 tmpW = max(1, tmpW / 2);
423 tmpH = max(1, tmpH / 2);
424 object->levels++;
426 TRACE("Calculated levels = %d\n", object->levels);
429 /* Generate all the surfaces */
430 tmpW = Width;
431 tmpH = Height;
432 for (i = 0; i < object->levels; i++)
434 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
435 object->surfaces[i]->Container = (IUnknown*) object;
436 object->surfaces[i]->myDesc.Usage = Usage;
437 object->surfaces[i]->myDesc.Pool = Pool;
438 /**
439 * As writen in msdn in IDirect3DTexture8::LockRect
440 * Textures created in D3DPOOL_DEFAULT are not lockable.
442 if (D3DPOOL_DEFAULT == Pool) {
443 object->surfaces[i]->lockable = FALSE;
446 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
447 tmpW = max(1, tmpW / 2);
448 tmpH = max(1, tmpH / 2);
451 *ppTexture = (LPDIRECT3DTEXTURE8) object;
452 return D3D_OK;
454 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
455 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
456 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
458 IDirect3DVolumeTexture8Impl *object;
459 int i;
460 UINT tmpW;
461 UINT tmpH;
462 UINT tmpD;
464 ICOM_THIS(IDirect3DDevice8Impl,iface);
466 /* Allocate the storage for it */
467 TRACE("(%p) : W(%d) H(%d) D(%d), Lvl(%d) Usage(%ld), Fmt(%u,%s), Pool(%s)\n", This, Width, Height, Depth, Levels, Usage, Format, debug_d3dformat(Format), debug_d3dpool(Pool));
468 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
469 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
470 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
471 object->Device = This;
472 object->ref = 1;
474 object->width = Width;
475 object->height = Height;
476 object->depth = Depth;
477 object->levels = Levels;
478 object->usage = Usage;
479 object->format = Format;
481 /* Calculate levels for mip mapping */
482 if (Levels == 0) {
483 object->levels++;
484 tmpW = Width;
485 tmpH = Height;
486 tmpD = Depth;
487 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
488 tmpW = max(1, tmpW / 2);
489 tmpH = max(1, tmpH / 2);
490 tmpD = max(1, tmpD / 2);
491 object->levels++;
493 TRACE("Calculated levels = %d\n", object->levels);
496 /* Generate all the surfaces */
497 tmpW = Width;
498 tmpH = Height;
499 tmpD = Depth;
501 for (i = 0; i < object->levels; i++)
503 IDirect3DVolume8Impl* volume;
505 /* Create the volume - No entry point for this seperately?? */
506 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
507 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
509 volume->lpVtbl = &Direct3DVolume8_Vtbl;
510 volume->Device = This;
511 volume->ResourceType = D3DRTYPE_VOLUME;
512 volume->Container = (IUnknown*) object;
513 volume->ref = 1;
515 volume->myDesc.Width = Width;
516 volume->myDesc.Height = Height;
517 volume->myDesc.Depth = Depth;
518 volume->myDesc.Format = Format;
519 volume->myDesc.Type = D3DRTYPE_VOLUME;
520 volume->myDesc.Pool = Pool;
521 volume->myDesc.Usage = Usage;
522 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
523 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
524 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
526 volume->lockable = TRUE;
527 volume->locked = FALSE;
528 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
529 volume->Dirty = FALSE;
530 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
532 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
533 This, Width, Height, Depth, Format, debug_d3dformat(Format),
534 volume, volume->allocatedMemory, volume->myDesc.Size);
536 tmpW = max(1, tmpW / 2);
537 tmpH = max(1, tmpH / 2);
538 tmpD = max(1, tmpD / 2);
541 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
542 return D3D_OK;
544 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
545 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
547 IDirect3DCubeTexture8Impl *object;
548 ICOM_THIS(IDirect3DDevice8Impl,iface);
549 int i,j;
550 UINT tmpW;
552 /* Allocate the storage for it */
553 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));
554 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
555 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
556 object->ref = 1;
557 object->Device = This;
558 object->ResourceType = D3DRTYPE_CUBETEXTURE;
560 object->edgeLength = EdgeLength;
561 object->levels = Levels;
562 object->usage = Usage;
563 object->format = Format;
565 /* Calculate levels for mip mapping */
566 if (Levels == 0) {
567 object->levels++;
568 tmpW = EdgeLength;
569 while (tmpW > 1) {
570 tmpW = max(1, tmpW / 2);
571 object->levels++;
573 TRACE("Calculated levels = %d\n", object->levels);
576 /* Generate all the surfaces */
577 tmpW = EdgeLength;
578 for (i = 0; i < object->levels; i++) {
579 /* Create the 6 faces */
580 for (j = 0; j < 6; j++) {
581 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
582 object->surfaces[j][i]->Container = (IUnknown*) object;
583 object->surfaces[j][i]->myDesc.Usage = Usage;
584 object->surfaces[j][i]->myDesc.Pool = Pool;
585 /**
586 * As writen in msdn in IDirect3DCubeTexture8::LockRect
587 * Textures created in D3DPOOL_DEFAULT are not lockable.
589 if (D3DPOOL_DEFAULT == Pool) {
590 object->surfaces[j][i]->lockable = FALSE;
593 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
595 tmpW = max(1, tmpW / 2);
598 TRACE("(%p) : Iface@%p\n", This, object);
599 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
600 return D3D_OK;
602 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
603 IDirect3DVertexBuffer8Impl *object;
605 ICOM_THIS(IDirect3DDevice8Impl,iface);
607 /* Allocate the storage for the device */
608 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
609 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
610 object->Device = This;
611 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
612 object->ref = 1;
613 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
614 object->currentDesc.Usage = Usage;
615 object->currentDesc.Pool = Pool;
616 object->currentDesc.FVF = FVF;
617 object->currentDesc.Size = Size;
619 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
621 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
623 return D3D_OK;
625 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
626 IDirect3DIndexBuffer8Impl *object;
628 ICOM_THIS(IDirect3DDevice8Impl,iface);
629 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
631 /* Allocate the storage for the device */
632 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
633 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
634 object->Device = This;
635 object->ref = 1;
636 object->ResourceType = D3DRTYPE_INDEXBUFFER;
638 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
639 object->currentDesc.Usage = Usage;
640 object->currentDesc.Pool = Pool;
641 object->currentDesc.Format = Format;
642 object->currentDesc.Size = Length;
644 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
646 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
648 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
650 return D3D_OK;
652 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
653 IDirect3DSurface8Impl *object;
654 ICOM_THIS(IDirect3DDevice8Impl,iface);
656 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
657 if (NULL == object) {
658 *ppSurface = NULL;
659 return D3DERR_OUTOFVIDEOMEMORY;
661 *ppSurface = (LPDIRECT3DSURFACE8) object;
662 object->lpVtbl = &Direct3DSurface8_Vtbl;
663 object->Device = This;
664 object->ResourceType = D3DRTYPE_SURFACE;
665 object->Container = (IUnknown*) This;
667 object->ref = 1;
668 object->myDesc.Width = Width;
669 object->myDesc.Height = Height;
670 object->myDesc.Format = Format;
671 object->myDesc.Type = D3DRTYPE_SURFACE;
672 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
673 object->myDesc.Pool = D3DPOOL_DEFAULT;
674 object->myDesc.MultiSampleType = MultiSample;
675 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
676 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
677 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
678 object->lockable = Lockable;
679 object->locked = FALSE;
680 memset(&object->lockedRect, 0, sizeof(RECT));
681 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
683 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->myDesc.Size);
684 return D3D_OK;
686 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
687 IDirect3DSurface8Impl *object;
689 ICOM_THIS(IDirect3DDevice8Impl,iface);
691 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
692 if (NULL == object) {
693 *ppSurface = NULL;
694 return D3DERR_OUTOFVIDEOMEMORY;
696 *ppSurface = (LPDIRECT3DSURFACE8) object;
697 object->lpVtbl = &Direct3DSurface8_Vtbl;
698 object->Device = This;
699 object->ResourceType = D3DRTYPE_SURFACE;
700 object->Container = (IUnknown*) This;
702 object->ref = 1;
703 object->myDesc.Width = Width;
704 object->myDesc.Height = Height;
705 object->myDesc.Format = Format;
706 object->myDesc.Type = D3DRTYPE_SURFACE;
707 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
708 object->myDesc.Pool = D3DPOOL_DEFAULT;
709 object->myDesc.MultiSampleType = MultiSample;
710 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
711 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
712 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
713 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
714 object->locked = FALSE;
715 memset(&object->lockedRect, 0, sizeof(RECT));
716 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
718 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->myDesc.Size);
719 return D3D_OK;
721 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
722 IDirect3DSurface8Impl *object;
724 ICOM_THIS(IDirect3DDevice8Impl,iface);
726 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
727 *ppSurface = (LPDIRECT3DSURFACE8) object;
728 object->lpVtbl = &Direct3DSurface8_Vtbl;
729 object->Device = This;
730 object->ResourceType = D3DRTYPE_SURFACE;
731 object->Container = (IUnknown*) This;
733 object->ref = 1;
734 object->myDesc.Width = Width;
735 object->myDesc.Height = Height;
736 object->myDesc.Format = Format;
737 object->myDesc.Type = D3DRTYPE_SURFACE;
738 object->myDesc.Usage = 0;
739 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
740 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
741 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
742 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
743 object->lockable = TRUE;
744 object->locked = FALSE;
745 memset(&object->lockedRect, 0, sizeof(RECT));
746 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
748 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->myDesc.Size);
749 return D3D_OK;
751 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
752 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
753 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
755 HRESULT rc = D3D_OK;
756 IDirect3DBaseTexture8* texture = NULL;
759 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
760 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
762 ICOM_THIS(IDirect3DDevice8Impl,iface);
763 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
764 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
766 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
767 a sample and doesnt seem to break anything as far as I can tell */
768 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
769 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
770 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
771 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
772 rc = D3DERR_INVALIDCALL;
774 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
775 TRACE("Converting dest to same format as source, since dest was unknown\n");
776 dst->myDesc.Format = src->myDesc.Format;
778 /* Convert container as well */
779 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
780 if (texture != NULL) {
781 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
782 /** Releasing texture after GetContainer */
783 IDirect3DBaseTexture8_Release(texture);
784 texture = NULL;
788 /* Quick if complete copy ... */
789 if (rc == D3D_OK && cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
791 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
793 D3DLOCKED_RECT lrSrc;
794 D3DLOCKED_RECT lrDst;
795 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
796 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
797 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
799 /*memcpy(dst->allocatedMemory, src->allocatedMemory, src->myDesc.Size);*/
800 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
802 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
803 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
804 TRACE("Unlocked src and dst\n");
806 } else {
808 FIXME("Wanted to copy all surfaces but size not compatible\n");
809 rc = D3DERR_INVALIDCALL;
813 } else {
815 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
817 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
818 int i;
819 /* Copy rect by rect */
820 for (i = 0; i < cRects; i++) {
821 CONST RECT* r = &pSourceRectsArray[i];
822 CONST POINT* p = &pDestPointsArray[i];
823 int copyperline = (r->right - r->left) * bytesPerPixel;
824 int j;
825 D3DLOCKED_RECT lrSrc;
826 D3DLOCKED_RECT lrDst;
827 RECT dest_rect;
830 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
832 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
833 dest_rect.left = p->x;
834 dest_rect.top = p->y;
835 dest_rect.right = p->x + (r->right - r->left);
836 dest_rect.left = p->y + (r->bottom - r->top);
837 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
838 TRACE("Locked src and dst\n");
840 /* Find where to start */
841 #if 0
842 from = copyfrom + (r->top * pitchFrom) + (r->left * bytesPerPixel);
843 to = copyto + (p->y * pitchTo) + (p->x * bytesPerPixel);
844 /* Copy line by line */
845 for (j = 0; j < (r->bottom - r->top); j++) {
846 memcpy(to + (j * pitchTo), from + (j * pitchFrom), copyperline);
848 #endif
850 for (j = 0; j < (r->bottom - r->top); j++) {
851 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
854 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
855 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
856 TRACE("Unlocked src and dst\n");
859 } else {
861 FIXME("Wanted to copy partial surfaces not implemented\n");
862 rc = D3DERR_INVALIDCALL;
867 return rc;
869 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
870 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
871 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
872 D3DRESOURCETYPE srcType;
873 D3DRESOURCETYPE dstType;
875 ICOM_THIS(IDirect3DDevice8Impl,iface);
876 TRACE("(%p) : first try\n", This);
878 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
879 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
881 if (srcType != dstType) {
882 return D3DERR_INVALIDCALL;
884 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
885 return D3DERR_INVALIDCALL;
887 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
888 return D3DERR_INVALIDCALL;
890 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
891 /** Only copy Dirty textures */
892 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
893 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
894 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
895 UINT i, j;
897 for (i = skipLevels; i < srcLevelCnt; ++i) {
898 HRESULT hr;
900 switch (srcType) {
901 case D3DRTYPE_TEXTURE:
903 IDirect3DSurface8* srcSur = NULL;
904 IDirect3DSurface8* dstSur = NULL;
905 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
906 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
907 /*IDirect3DDevice8_CopyRects*/
908 IDirect3DSurface8Impl_Release(srcSur);
909 IDirect3DSurface8Impl_Release(dstSur);
911 break;
912 case D3DRTYPE_VOLUMETEXTURE:
914 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
916 break;
917 case D3DRTYPE_CUBETEXTURE:
919 IDirect3DSurface8* srcSur = NULL;
920 IDirect3DSurface8* dstSur = NULL;
921 for (j = 0; j < 5; ++j) {
922 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
923 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
924 /*IDirect3DDevice8_CopyRects*/
925 IDirect3DSurface8Impl_Release(srcSur);
926 IDirect3DSurface8Impl_Release(dstSur);
929 break;
930 default:
931 break;
934 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
937 return D3D_OK;
939 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
940 HRESULT hr;
941 D3DLOCKED_RECT lockedRect;
942 RECT wantedRect;
943 GLint prev_store;
944 GLenum prev_read;
946 ICOM_THIS(IDirect3DDevice8Impl,iface);
948 FIXME("(%p) : see if behavior correct\n", This);
950 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
951 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
952 return D3DERR_INVALIDCALL;
955 wantedRect.left = 0;
956 wantedRect.top = 0;
957 wantedRect.right = This->PresentParms.BackBufferWidth;
958 wantedRect.bottom = This->PresentParms.BackBufferHeight;
960 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
961 if (FAILED(hr)) {
962 ERR("(%p) : cannot lock surface\n", This);
963 return D3DERR_INVALIDCALL;
966 ENTER_GL();
970 IDirect3DSurface8Impl* tmp = ((IDirect3DSurface8Impl*) pDestSurface);
971 FIXME("dest:%u,%u,bpp:%u\n", tmp->myDesc.Width, tmp->myDesc.Height, tmp->bytesPerPixel);
972 FIXME("dest2:pitch%u\n", lockedRect.Pitch);
973 FIXME("src:%u,%u\n", This->PresentParms.BackBufferWidth, This->PresentParms.BackBufferHeight);
974 tmp = This->frontBuffer;
975 FIXME("src2:%u,%u,bpp:%u\n", tmp->myDesc.Width, tmp->myDesc.Height, tmp->bytesPerPixel);
979 glFlush();
980 vcheckGLcall("glFlush");
981 glGetIntegerv(GL_READ_BUFFER, &prev_read);
982 vcheckGLcall("glIntegerv");
983 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
984 vcheckGLcall("glIntegerv");
986 glReadBuffer(GL_FRONT);
987 vcheckGLcall("glReadBuffer");
988 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
989 vcheckGLcall("glPixelStorei");
990 /* stupid copy */
992 long j;
993 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
994 /*memcpy(lockedRect.pBits + (j * lockedRect.Pitch), This->frontBuffer->allocatedMemory + (j * i), i);*/
995 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
996 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
997 vcheckGLcall("glReadPixels");
1000 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1001 vcheckGLcall("glPixelStorei");
1002 glReadBuffer(prev_read);
1003 vcheckGLcall("glReadBuffer");
1005 LEAVE_GL();
1007 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1008 return hr;
1010 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1011 HRESULT hr;
1013 ICOM_THIS(IDirect3DDevice8Impl,iface);
1015 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1016 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1017 return D3D_OK;
1020 IDirect3DDevice8Impl_CleanRender(iface);
1022 if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1023 IDirect3DSurface8Impl* tmp;
1025 TRACE("retoring SetRenderTarget defaults\n");
1027 tmp = This->renderTarget;
1028 This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer;
1029 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
1030 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1032 tmp = This->stencilBufferTarget;
1033 This->stencilBufferTarget = (IDirect3DSurface8Impl*) This->depthStencilBuffer;
1034 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
1035 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1037 return D3D_OK;
1040 TRACE("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1042 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1044 return hr;
1047 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1048 ICOM_THIS(IDirect3DDevice8Impl,iface);
1050 TRACE("(%p)->(%p) default(%p)\n", This, This->renderTarget, This->frontBuffer);
1052 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1053 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1055 return D3D_OK;
1058 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1059 ICOM_THIS(IDirect3DDevice8Impl,iface);
1061 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1063 /* Note inc ref on returned surface */
1064 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1065 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1067 return D3D_OK;
1070 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1071 ICOM_THIS(IDirect3DDevice8Impl,iface);
1072 TRACE("(%p) : stub\n", This);
1073 return D3D_OK;
1075 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1076 IDirect3DBaseTexture8* cont = NULL;
1077 HRESULT hr;
1078 ICOM_THIS(IDirect3DDevice8Impl,iface);
1079 TRACE("(%p)\n", This);
1081 ENTER_GL();
1083 glFlush();
1084 checkGLcall("glFlush");
1086 /* Useful for debugging sometimes!
1087 printf("Hit Enter ...\n");
1088 getchar(); */
1090 if (This->frontBuffer != This->renderTarget) {
1092 GLenum prev_read;
1093 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1094 vcheckGLcall("glIntegerv");
1095 glReadBuffer(GL_BACK);
1096 vcheckGLcall("glReadBuffer");
1098 long j;
1099 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1100 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1101 glReadPixels(0,
1102 This->renderTarget->myDesc.Height - j - 1,
1103 This->renderTarget->myDesc.Width,
1105 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1106 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1107 This->renderTarget->allocatedMemory + j * pitch);
1108 vcheckGLcall("glReadPixels");
1111 glReadBuffer(prev_read);
1112 vcheckGLcall("glReadBuffer");
1115 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1116 if (SUCCEEDED(hr) && NULL != cont) {
1117 /** always dirtify for now. we must find a better way to see that surface have been modified */
1118 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1119 IDirect3DBaseTexture8_PreLoad(cont);
1120 IDirect3DBaseTexture8Impl_Release(cont);
1121 cont = NULL;
1125 LEAVE_GL();
1126 return D3D_OK;
1128 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1129 ICOM_THIS(IDirect3DDevice8Impl,iface);
1131 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1132 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1133 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1134 GLbitfield glMask = 0;
1135 GLboolean old_ztest;
1136 GLfloat old_z_clear_value;
1137 GLint old_stencil_clear_value;
1138 GLfloat old_color_clear_value[4];
1139 int i;
1140 CONST D3DRECT* curRect;
1142 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1143 Count, pRects, Flags, Z, Stencil);
1145 ENTER_GL();
1146 if (Count > 0 && pRects) {
1147 glEnable(GL_SCISSOR_TEST);
1148 checkGLcall("glEnable GL_SCISSOR_TEST");
1149 curRect = pRects;
1150 } else {
1151 curRect = NULL;
1154 /* Only set the values up once, as they are not changing */
1155 if (Flags & D3DCLEAR_STENCIL) {
1156 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1157 glClearStencil(Stencil);
1158 checkGLcall("glClearStencil");
1159 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1162 if (Flags & D3DCLEAR_ZBUFFER) {
1163 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1164 glDepthMask(GL_TRUE);
1165 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1166 glClearDepth(Z);
1167 checkGLcall("glClearDepth");
1168 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1171 if (Flags & D3DCLEAR_TARGET) {
1172 TRACE("Clearing screen with glClear to color %lx\n", Color);
1173 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1174 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1175 ((Color >> 8) & 0xFF) / 255.0f,
1176 ((Color >> 0) & 0xFF) / 255.0f,
1177 ((Color >> 24) & 0xFF) / 255.0f);
1178 checkGLcall("glClearColor");
1179 glMask = glMask | GL_COLOR_BUFFER_BIT;
1182 /* Now process each rect in turn */
1183 for (i = 0; i < Count || i == 0; i++) {
1185 if (curRect) {
1186 /* Note gl uses lower left, width/height */
1187 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1188 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1189 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1190 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1191 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1192 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1193 checkGLcall("glScissor");
1196 /* Clear the selected rectangle (or full screen) */
1197 glClear(glMask);
1198 checkGLcall("glClear");
1200 /* Step to the next rectangle */
1201 if (curRect) curRect = curRect + sizeof(D3DRECT);
1204 /* Restore the old values (why..?) */
1205 if (Flags & D3DCLEAR_STENCIL) {
1206 glClearStencil(old_stencil_clear_value);
1208 if (Flags & D3DCLEAR_ZBUFFER) {
1209 glDepthMask(old_ztest);
1210 glClearDepth(old_z_clear_value);
1212 if (Flags & D3DCLEAR_TARGET) {
1213 glClearColor(old_color_clear_value[0],
1214 old_color_clear_value[1],
1215 old_color_clear_value[2],
1216 old_color_clear_value[3]);
1219 if (Count > 0 && pRects) {
1220 glDisable(GL_SCISSOR_TEST);
1221 checkGLcall("glDisable");
1223 LEAVE_GL();
1225 return D3D_OK;
1227 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1228 ICOM_THIS(IDirect3DDevice8Impl,iface);
1229 D3DMATRIX m;
1230 int k;
1231 float f;
1232 BOOL viewChanged = TRUE;
1233 int Stage;
1235 /* Most of this routine, comments included copied from ddraw tree initially: */
1236 TRACE("(%p) : State=%d\n", This, d3dts);
1238 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1239 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1240 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1242 /* Handle recording of state blocks */
1243 if (This->isRecordingState) {
1244 TRACE("Recording... not performing anything\n");
1245 return D3D_OK;
1249 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1251 where ViewMat = Camera space, WorldMat = world space.
1253 In OpenGL, camera and world space is combined into GL_MODELVIEW
1254 matrix. The Projection matrix stay projection matrix. */
1256 /* After reading through both OpenGL and Direct3D documentations, I
1257 thought that D3D matrices were written in 'line major mode' transposed
1258 from OpenGL's 'column major mode'. But I found out that a simple memcpy
1259 works fine to transfer one matrix format to the other (it did not work
1260 when transposing)....
1262 So :
1263 1) are the documentations wrong
1264 2) does the matrix work even if they are not read correctly
1265 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
1266 loading using glLoadMatrix ?
1268 Anyway, I always use 'conv_mat' to transfer the matrices from one format
1269 to the other so that if I ever find out that I need to transpose them, I
1270 will able to do it quickly, only by changing the macro conv_mat. */
1272 if (d3dts < 256) {
1273 switch (d3dts) {
1274 case D3DTS_VIEW:
1275 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_VIEW]);
1276 break;
1278 case D3DTS_PROJECTION:
1279 conv_mat(lpmatrix, &This->StateBlock->transforms[D3DTS_PROJECTION]);
1280 break;
1282 case D3DTS_TEXTURE0:
1283 case D3DTS_TEXTURE1:
1284 case D3DTS_TEXTURE2:
1285 case D3DTS_TEXTURE3:
1286 case D3DTS_TEXTURE4:
1287 case D3DTS_TEXTURE5:
1288 case D3DTS_TEXTURE6:
1289 case D3DTS_TEXTURE7:
1290 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
1291 break;
1293 default:
1294 FIXME("Unhandled transform state!!\n");
1295 break;
1297 } else {
1298 /**
1299 * Indexed Vertex Blending Matrices 256 -> 511
1300 * where WORLDMATRIX(0) == 256!
1302 /** store it */
1303 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts]);
1304 #if 0
1305 if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
1306 FIXME("TODO\n");
1307 } else if (GL_SUPPORT(EXT_VERTEX_WEIGHTING)) {
1308 FIXME("TODO\n");
1310 #endif
1314 * Move the GL operation to outside of switch to make it work
1315 * regardless of transform set order.
1317 ENTER_GL();
1318 if (memcmp(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX))) {
1319 glMatrixMode(GL_PROJECTION);
1320 checkGLcall("glMatrixMode");
1321 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0]);
1322 checkGLcall("glLoadMatrixf");
1323 memcpy(&This->lastProj, &This->StateBlock->transforms[D3DTS_PROJECTION].u.m[0][0], sizeof(D3DMATRIX));
1324 } else {
1325 TRACE("Skipping as projection already correct\n");
1328 glMatrixMode(GL_MODELVIEW);
1329 checkGLcall("glMatrixMode");
1330 viewChanged = FALSE;
1331 if (memcmp(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX))) {
1332 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1333 checkGLcall("glLoadMatrixf");
1334 memcpy(&This->lastView, &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0], sizeof(D3DMATRIX));
1335 viewChanged = TRUE;
1337 /* If we are changing the View matrix, reset the light and clipping planes to the new view */
1338 if (d3dts == D3DTS_VIEW) {
1340 /* NOTE: We have to reset the positions even if the light/plane is not currently
1341 enabled, since the call to enable it will not reset the position. */
1343 /* Reset lights */
1344 for (k = 0; k < GL_LIMITS(lights); k++) {
1345 glLightfv(GL_LIGHT0 + k, GL_POSITION, &This->lightPosn[k][0]);
1346 checkGLcall("glLightfv posn");
1347 glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, &This->lightDirn[k][0]);
1348 checkGLcall("glLightfv dirn");
1351 /* Reset Clipping Planes if clipping is enabled */
1352 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1353 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1354 checkGLcall("glClipPlane");
1357 /* Reapply texture transforms as based off modelview when applied */
1358 for (Stage = 0; Stage < GL_LIMITS(textures); Stage++) {
1360 /* Only applicable if the transforms are not disabled */
1361 if (This->UpdateStateBlock->texture_state[Stage][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)
1363 /* Now apply texture transforms if not applying to the dummy textures */
1364 #if defined(GL_VERSION_1_3)
1365 glActiveTexture(GL_TEXTURE0 + Stage);
1366 #else
1367 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
1368 #endif
1369 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage);");
1371 glMatrixMode(GL_TEXTURE);
1372 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
1373 glLoadIdentity();
1374 } else {
1375 D3DMATRIX fred;
1376 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
1377 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
1380 checkGLcall("Load matrix for texture");
1382 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
1384 } else if ((d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) &&
1385 (This->UpdateStateBlock->texture_state[d3dts - D3DTS_TEXTURE0][D3DTSS_TEXTURETRANSFORMFLAGS] != D3DTTFF_DISABLE)) {
1386 /* Now apply texture transforms if not applying to the dummy textures */
1387 Stage = d3dts - D3DTS_TEXTURE0;
1389 if (memcmp(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], sizeof(D3DMATRIX))) {
1390 memcpy(&This->lastTexTrans[Stage], &This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], sizeof(D3DMATRIX));
1392 #if defined(GL_VERSION_1_3)
1393 glActiveTexture(GL_TEXTURE0 + Stage);
1394 #else
1395 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
1396 #endif
1397 checkGLcall("glActiveTexture(GL_TEXTURE0 + Stage)");
1399 glMatrixMode(GL_TEXTURE);
1400 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
1401 glLoadIdentity();
1402 } else {
1403 D3DMATRIX fred;
1404 conv_mat(&This->StateBlock->transforms[D3DTS_TEXTURE0+Stage], &fred);
1405 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_TEXTURE0+Stage].u.m[0][0]);
1407 checkGLcall("Load matrix for texture");
1408 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
1409 } else {
1410 TRACE("Skipping texture transform as already correct\n");
1413 } else {
1414 TRACE("Skipping view setup as view already correct\n");
1418 * Vertex Blending as described
1419 * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/directx9_c/directx/graphics/reference/d3d/enums/d3dvertexblendflags.asp
1421 switch (This->UpdateStateBlock->vertex_blend) {
1422 case D3DVBF_DISABLE:
1424 if (viewChanged == TRUE ||
1425 (memcmp(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX)))) {
1426 memcpy(&This->lastWorld0, &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0], sizeof(D3DMATRIX));
1427 if (viewChanged == FALSE) {
1428 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1429 checkGLcall("glLoadMatrixf");
1431 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
1432 checkGLcall("glMultMatrixf");
1433 } else {
1434 TRACE("Skipping as world already correct\n");
1437 break;
1438 case D3DVBF_1WEIGHTS:
1439 case D3DVBF_2WEIGHTS:
1440 case D3DVBF_3WEIGHTS:
1442 FIXME("valid/correct D3DVBF_[1..3]WEIGHTS\n");
1444 * doc seems to say that the weight values must be in vertex data (specified in FVF by D3DFVF_XYZB*)
1445 * so waiting for the values before matrix work
1446 for (k = 0; k < This->UpdateStateBlock->vertex_blend; ++k) {
1447 glMultMatrixf((float *) &This->StateBlock->transforms[D3DTS_WORLDMATRIX(k)].u.m[0][0]);
1448 checkGLcall("glMultMatrixf");
1452 break;
1453 case D3DVBF_TWEENING:
1455 FIXME("valid/correct D3DVBF_TWEENING\n");
1456 f = This->UpdateStateBlock->tween_factor;
1457 m.u.s._11 = f; m.u.s._12 = f; m.u.s._13 = f; m.u.s._14 = f;
1458 m.u.s._21 = f; m.u.s._22 = f; m.u.s._23 = f; m.u.s._24 = f;
1459 m.u.s._31 = f; m.u.s._32 = f; m.u.s._33 = f; m.u.s._34 = f;
1460 m.u.s._41 = f; m.u.s._42 = f; m.u.s._43 = f; m.u.s._44 = f;
1461 if (viewChanged == FALSE) {
1462 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1463 checkGLcall("glLoadMatrixf");
1465 glMultMatrixf((float *) &m.u.m[0][0]);
1466 checkGLcall("glMultMatrixf");
1468 break;
1469 case D3DVBF_0WEIGHTS:
1471 FIXME("valid/correct D3DVBF_0WEIGHTS\n");
1472 /* single matrix of weight 1.0f */
1473 m.u.s._11 = 1.0f; m.u.s._12 = 1.0f; m.u.s._13 = 1.0f; m.u.s._14 = 1.0f;
1474 m.u.s._21 = 1.0f; m.u.s._22 = 1.0f; m.u.s._23 = 1.0f; m.u.s._24 = 1.0f;
1475 m.u.s._31 = 1.0f; m.u.s._32 = 1.0f; m.u.s._33 = 1.0f; m.u.s._34 = 1.0f;
1476 m.u.s._41 = 1.0f; m.u.s._42 = 1.0f; m.u.s._43 = 1.0f; m.u.s._44 = 1.0f;
1477 if (viewChanged == FALSE) {
1478 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1479 checkGLcall("glLoadMatrixf");
1481 glMultMatrixf((float *) &m.u.m[0][0]);
1482 checkGLcall("glMultMatrixf");
1484 break;
1485 default:
1486 break; /* stupid compilator */
1489 LEAVE_GL();
1491 return D3D_OK;
1494 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1495 ICOM_THIS(IDirect3DDevice8Impl,iface);
1496 TRACE("(%p) : for State %d\n", This, State);
1497 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1498 return D3D_OK;
1501 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1502 D3DMATRIX *mat = NULL;
1503 D3DMATRIX temp;
1505 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1506 but works regardless of recording being on.
1507 If this is found to be wrong, change to StateBlock. */
1508 ICOM_THIS(IDirect3DDevice8Impl,iface);
1509 TRACE("(%p) : For state %u\n", This, State);
1511 if (State < HIGHEST_TRANSFORMSTATE)
1513 mat = &This->UpdateStateBlock->transforms[State];
1514 } else {
1515 FIXME("Unhandled transform state!!\n");
1518 /* Copied from ddraw code: */
1519 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);
1520 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);
1521 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);
1522 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);
1524 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);
1525 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);
1526 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);
1527 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);
1529 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);
1530 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);
1531 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);
1532 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);
1534 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);
1535 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);
1536 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);
1537 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);
1539 /* Apply change via set transform - will reapply to eg. lights this way */
1540 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1541 return D3D_OK;
1543 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1544 ICOM_THIS(IDirect3DDevice8Impl,iface);
1546 TRACE("(%p)\n", This);
1547 This->UpdateStateBlock->Changed.viewport = TRUE;
1548 This->UpdateStateBlock->Set.viewport = TRUE;
1549 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1551 /* Handle recording of state blocks */
1552 if (This->isRecordingState) {
1553 TRACE("Recording... not performing anything\n");
1554 return D3D_OK;
1557 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1558 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1560 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1561 checkGLcall("glDepthRange");
1562 /* Note: GL requires lower left, DirectX supplies upper left */
1563 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
1564 pViewport->Width, pViewport->Height);
1565 checkGLcall("glViewport");
1568 return D3D_OK;
1571 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1572 ICOM_THIS(IDirect3DDevice8Impl,iface);
1573 TRACE("(%p)\n", This);
1574 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1575 return D3D_OK;
1578 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1579 ICOM_THIS(IDirect3DDevice8Impl,iface);
1581 This->UpdateStateBlock->Changed.material = TRUE;
1582 This->UpdateStateBlock->Set.material = TRUE;
1583 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1585 /* Handle recording of state blocks */
1586 if (This->isRecordingState) {
1587 TRACE("Recording... not performing anything\n");
1588 return D3D_OK;
1591 ENTER_GL();
1592 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1593 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1594 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1595 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1596 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1598 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1599 checkGLcall("glMaterialfv");
1600 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1601 checkGLcall("glMaterialfv");
1603 /* Only change material color if specular is enabled, otherwise it is set to black */
1604 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1605 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1606 checkGLcall("glMaterialfv");
1608 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1609 checkGLcall("glMaterialfv");
1610 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1611 checkGLcall("glMaterialf");
1613 LEAVE_GL();
1614 return D3D_OK;
1616 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1617 ICOM_THIS(IDirect3DDevice8Impl,iface);
1618 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1619 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1620 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1621 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1622 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1623 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1624 return D3D_OK;
1627 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1628 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
1629 float rho;
1630 float quad_att;
1632 ICOM_THIS(IDirect3DDevice8Impl,iface);
1633 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1635 if (Index >= GL_LIMITS(lights)) {
1636 TRACE("Cannot handle more lights than device supports\n");
1637 return D3DERR_INVALIDCALL;
1640 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,
1641 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1642 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1643 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1644 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1645 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1646 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1648 This->UpdateStateBlock->Changed.lights[Index] = TRUE;
1649 This->UpdateStateBlock->Set.lights[Index] = TRUE;
1650 memcpy(&This->UpdateStateBlock->lights[Index], pLight, sizeof(D3DLIGHT8));
1652 /* Handle recording of state blocks */
1653 if (This->isRecordingState) {
1654 TRACE("Recording... not performing anything\n");
1655 return D3D_OK;
1658 /* Diffuse: */
1659 colRGBA[0] = pLight->Diffuse.r;
1660 colRGBA[1] = pLight->Diffuse.g;
1661 colRGBA[2] = pLight->Diffuse.b;
1662 colRGBA[3] = pLight->Diffuse.a;
1663 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
1664 checkGLcall("glLightfv");
1666 /* Specular */
1667 colRGBA[0] = pLight->Specular.r;
1668 colRGBA[1] = pLight->Specular.g;
1669 colRGBA[2] = pLight->Specular.b;
1670 colRGBA[3] = pLight->Specular.a;
1671 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
1672 checkGLcall("glLightfv");
1674 /* Ambient */
1675 colRGBA[0] = pLight->Ambient.r;
1676 colRGBA[1] = pLight->Ambient.g;
1677 colRGBA[2] = pLight->Ambient.b;
1678 colRGBA[3] = pLight->Ambient.a;
1679 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
1680 checkGLcall("glLightfv");
1682 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
1683 glMatrixMode(GL_MODELVIEW);
1684 glPushMatrix();
1685 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1687 /* Attenuation - Are these right? guessing... */
1688 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, pLight->Attenuation0);
1689 checkGLcall("glLightf");
1690 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, pLight->Attenuation1);
1691 checkGLcall("glLightf");
1693 quad_att = 1.4/(pLight->Range*pLight->Range);
1694 if (quad_att < pLight->Attenuation2) quad_att = pLight->Attenuation2;
1695 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
1696 checkGLcall("glLightf");
1698 switch (pLight->Type) {
1699 case D3DLIGHT_POINT:
1700 /* Position */
1701 This->lightPosn[Index][0] = pLight->Position.x;
1702 This->lightPosn[Index][1] = pLight->Position.y;
1703 This->lightPosn[Index][2] = pLight->Position.z;
1704 This->lightPosn[Index][3] = 1.0;
1705 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
1706 checkGLcall("glLightfv");
1708 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, 180);
1709 checkGLcall("glLightf");
1711 /* FIXME: Range */
1712 break;
1714 case D3DLIGHT_SPOT:
1715 /* Position */
1716 This->lightPosn[Index][0] = pLight->Position.x;
1717 This->lightPosn[Index][1] = pLight->Position.y;
1718 This->lightPosn[Index][2] = pLight->Position.z;
1719 This->lightPosn[Index][3] = 1.0;
1720 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
1721 checkGLcall("glLightfv");
1723 /* Direction */
1724 This->lightDirn[Index][0] = pLight->Direction.x;
1725 This->lightDirn[Index][1] = pLight->Direction.y;
1726 This->lightDirn[Index][2] = pLight->Direction.z;
1727 This->lightDirn[Index][3] = 1.0;
1728 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &This->lightDirn[Index][0]);
1729 checkGLcall("glLightfv");
1732 * opengl-ish and d3d-ish spot lights use too different models for the
1733 * light "intensity" as a function of the angle towards the main light direction,
1734 * so we only can approximate very roughly.
1735 * however spot lights are rather rarely used in games (if ever used at all).
1736 * furthermore if still used, probably nobody pays attention to such details.
1738 if (pLight->Falloff == 0) {
1739 rho = 6.28f;
1740 } else {
1741 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1743 if (rho < 0.0001) rho = 0.0001f;
1744 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, -0.3/log(cos(rho/2)));
1745 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, pLight->Phi*90/M_PI);
1747 /* FIXME: Range */
1748 break;
1749 case D3DLIGHT_DIRECTIONAL:
1750 /* Direction */
1751 This->lightPosn[Index][0] = -pLight->Direction.x;
1752 This->lightPosn[Index][1] = -pLight->Direction.y;
1753 This->lightPosn[Index][2] = -pLight->Direction.z;
1754 This->lightPosn[Index][3] = 0.0;
1755 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]); /* Note gl uses w position of 0 for direction! */
1756 checkGLcall("glLightfv");
1758 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f);
1759 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
1762 break;
1763 default:
1764 FIXME("Unrecognized light type %d\n", pLight->Type);
1767 /* Restore the modelview matrix */
1768 glPopMatrix();
1770 return D3D_OK;
1772 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1773 ICOM_THIS(IDirect3DDevice8Impl,iface);
1774 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1776 if (Index >= GL_LIMITS(lights)) {
1777 TRACE("Cannot handle more lights than device supports\n");
1778 return D3DERR_INVALIDCALL;
1781 memcpy(pLight, &This->StateBlock->lights[Index], sizeof(D3DLIGHT8));
1782 return D3D_OK;
1784 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1785 ICOM_THIS(IDirect3DDevice8Impl,iface);
1786 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1788 if (Index >= GL_LIMITS(lights)) {
1789 TRACE("Cannot handle more lights than device supports\n");
1790 return D3DERR_INVALIDCALL;
1793 This->UpdateStateBlock->Changed.lightEnable[Index] = TRUE;
1794 This->UpdateStateBlock->Set.lightEnable[Index] = TRUE;
1795 This->UpdateStateBlock->lightEnable[Index] = Enable;
1797 /* Handle recording of state blocks */
1798 if (This->isRecordingState) {
1799 TRACE("Recording... not performing anything\n");
1800 return D3D_OK;
1803 if (Enable) {
1804 glEnable(GL_LIGHT0 + Index);
1805 checkGLcall("glEnable GL_LIGHT0+Index");
1806 } else {
1807 glDisable(GL_LIGHT0 + Index);
1808 checkGLcall("glDisable GL_LIGHT0+Index");
1810 return D3D_OK;
1812 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
1813 ICOM_THIS(IDirect3DDevice8Impl,iface);
1814 TRACE("(%p) : for idx(%ld)\n", This, Index);
1816 if (Index >= GL_LIMITS(lights)) {
1817 TRACE("Cannot handle more lights than device supports\n");
1818 return D3DERR_INVALIDCALL;
1821 *pEnable = This->StateBlock->lightEnable[Index];
1822 return D3D_OK;
1824 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
1825 ICOM_THIS(IDirect3DDevice8Impl,iface);
1826 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
1828 /* Validate Index */
1829 if (Index >= GL_LIMITS(clipplanes)) {
1830 TRACE("Application has requested clipplane this device doesnt support\n");
1831 return D3DERR_INVALIDCALL;
1834 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
1835 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
1836 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
1837 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
1838 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
1839 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
1841 /* Handle recording of state blocks */
1842 if (This->isRecordingState) {
1843 TRACE("Recording... not performing anything\n");
1844 return D3D_OK;
1847 /* Apply it */
1849 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
1850 glMatrixMode(GL_MODELVIEW);
1851 glPushMatrix();
1852 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1854 TRACE("Clipplane [%f,%f,%f,%f]\n",
1855 This->UpdateStateBlock->clipplane[Index][0],
1856 This->UpdateStateBlock->clipplane[Index][1],
1857 This->UpdateStateBlock->clipplane[Index][2],
1858 This->UpdateStateBlock->clipplane[Index][3]);
1859 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
1861 glPopMatrix();
1862 checkGLcall("glClipPlane");
1864 return D3D_OK;
1866 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
1867 ICOM_THIS(IDirect3DDevice8Impl,iface);
1868 TRACE("(%p) : for idx %ld\n", This, Index);
1870 /* Validate Index */
1871 if (Index >= GL_LIMITS(clipplanes)) {
1872 TRACE("Application has requested clipplane this device doesnt support\n");
1873 return D3DERR_INVALIDCALL;
1876 pPlane[0] = This->StateBlock->clipplane[Index][0];
1877 pPlane[1] = This->StateBlock->clipplane[Index][1];
1878 pPlane[2] = This->StateBlock->clipplane[Index][2];
1879 pPlane[3] = This->StateBlock->clipplane[Index][3];
1880 return D3D_OK;
1882 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
1883 ICOM_THIS(IDirect3DDevice8Impl,iface);
1884 DWORD OldValue = This->StateBlock->renderstate[State];
1886 TRACE("(%p)->state = %d, value = %ld\n", This, State, Value);
1887 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
1888 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
1889 This->UpdateStateBlock->renderstate[State] = Value;
1891 /* Handle recording of state blocks */
1892 if (This->isRecordingState) {
1893 TRACE("Recording... not performing anything\n");
1894 return D3D_OK;
1897 switch (State) {
1898 case D3DRS_FILLMODE :
1899 switch ((D3DFILLMODE) Value) {
1900 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
1901 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
1902 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
1903 default:
1904 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
1906 checkGLcall("glPolygonMode (fillmode)");
1907 break;
1909 case D3DRS_LIGHTING :
1910 if (Value) {
1911 glEnable(GL_LIGHTING);
1912 checkGLcall("glEnable GL_LIGHTING");
1913 } else {
1914 glDisable(GL_LIGHTING);
1915 checkGLcall("glDisable GL_LIGHTING");
1917 break;
1919 case D3DRS_ZENABLE :
1920 switch ((D3DZBUFFERTYPE) Value) {
1921 case D3DZB_FALSE:
1922 glDisable(GL_DEPTH_TEST);
1923 checkGLcall("glDisable GL_DEPTH_TEST");
1924 break;
1925 case D3DZB_TRUE:
1926 glEnable(GL_DEPTH_TEST);
1927 checkGLcall("glEnable GL_DEPTH_TEST");
1928 break;
1930 case D3DZB_USEW:
1931 default:
1932 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
1934 break;
1936 case D3DRS_CULLMODE :
1938 /* If we are culling "back faces with clockwise vertices" then
1939 set front faces to be counter clockwise and enable culling
1940 of back faces */
1941 switch ((D3DCULL) Value) {
1942 case D3DCULL_NONE:
1943 glDisable(GL_CULL_FACE);
1944 checkGLcall("glDisable GL_CULL_FACE");
1945 break;
1946 case D3DCULL_CW:
1947 glEnable(GL_CULL_FACE);
1948 checkGLcall("glEnable GL_CULL_FACE");
1949 glFrontFace(GL_CCW);
1950 checkGLcall("glFrontFace GL_CCW");
1951 glCullFace(GL_BACK);
1952 break;
1953 case D3DCULL_CCW:
1954 glEnable(GL_CULL_FACE);
1955 checkGLcall("glEnable GL_CULL_FACE");
1956 glFrontFace(GL_CW);
1957 checkGLcall("glFrontFace GL_CW");
1958 glCullFace(GL_BACK);
1959 break;
1960 default:
1961 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
1963 break;
1965 case D3DRS_SHADEMODE :
1966 switch ((D3DSHADEMODE) Value) {
1967 case D3DSHADE_FLAT:
1968 glShadeModel(GL_FLAT);
1969 checkGLcall("glShadeModel");
1970 break;
1971 case D3DSHADE_GOURAUD:
1972 glShadeModel(GL_SMOOTH);
1973 checkGLcall("glShadeModel");
1974 break;
1975 case D3DSHADE_PHONG:
1976 FIXME("D3DSHADE_PHONG isnt supported?\n");
1977 return D3DERR_INVALIDCALL;
1978 default:
1979 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
1981 break;
1983 case D3DRS_DITHERENABLE :
1984 if (Value) {
1985 glEnable(GL_DITHER);
1986 checkGLcall("glEnable GL_DITHER");
1987 } else {
1988 glDisable(GL_DITHER);
1989 checkGLcall("glDisable GL_DITHER");
1991 break;
1993 case D3DRS_ZWRITEENABLE :
1994 if (Value) {
1995 glDepthMask(1);
1996 checkGLcall("glDepthMask");
1997 } else {
1998 glDepthMask(0);
1999 checkGLcall("glDepthMask");
2001 break;
2003 case D3DRS_ZFUNC :
2005 int glParm = GL_LESS;
2007 switch ((D3DCMPFUNC) Value) {
2008 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2009 case D3DCMP_LESS: glParm=GL_LESS; break;
2010 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2011 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2012 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2013 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2014 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2015 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2016 default:
2017 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2019 glDepthFunc(glParm);
2020 checkGLcall("glDepthFunc");
2022 break;
2024 case D3DRS_AMBIENT :
2026 float col[4];
2027 D3DCOLORTOGLFLOAT4(Value, col);
2028 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2029 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2030 checkGLcall("glLightModel for MODEL_AMBIENT");
2033 break;
2035 case D3DRS_ALPHABLENDENABLE :
2036 if (Value) {
2037 glEnable(GL_BLEND);
2038 checkGLcall("glEnable GL_BLEND");
2039 } else {
2040 glDisable(GL_BLEND);
2041 checkGLcall("glDisable GL_BLEND");
2043 break;
2045 case D3DRS_SRCBLEND :
2046 case D3DRS_DESTBLEND :
2048 int newVal = GL_ZERO;
2049 switch (Value) {
2050 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2051 case D3DBLEND_ONE : newVal = GL_ONE; break;
2052 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2053 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2054 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2055 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2056 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2057 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2058 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2059 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2060 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2062 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2063 This->srcBlend = newVal;
2064 This->dstBlend = newVal;
2065 break;
2067 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2068 This->srcBlend = newVal;
2069 This->dstBlend = newVal;
2070 break;
2071 default:
2072 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2075 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2076 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2077 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2078 glBlendFunc(This->srcBlend, This->dstBlend);
2080 checkGLcall("glBlendFunc");
2082 break;
2084 case D3DRS_ALPHATESTENABLE :
2085 if (Value) {
2086 glEnable(GL_ALPHA_TEST);
2087 checkGLcall("glEnable GL_ALPHA_TEST");
2088 } else {
2089 glDisable(GL_ALPHA_TEST);
2090 checkGLcall("glDisable GL_ALPHA_TEST");
2092 break;
2094 case D3DRS_ALPHAFUNC :
2096 int glParm = GL_LESS;
2097 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2099 switch ((D3DCMPFUNC) Value) {
2100 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2101 case D3DCMP_LESS: glParm = GL_LESS; break;
2102 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2103 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2104 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2105 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2106 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2107 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2108 default:
2109 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2111 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2112 glAlphaFunc(glParm, ref);
2113 This->alphafunc = glParm;
2114 checkGLcall("glAlphaFunc");
2116 break;
2118 case D3DRS_ALPHAREF :
2120 int glParm = This->alphafunc;
2121 float ref = 1.0f;
2123 ref = ((float) Value) / 255.0f;
2124 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2125 glAlphaFunc(glParm, ref);
2126 checkGLcall("glAlphaFunc");
2128 break;
2130 case D3DRS_CLIPPLANEENABLE :
2131 case D3DRS_CLIPPING :
2133 /* Ensure we only do the changed clip planes */
2134 DWORD enable = 0xFFFFFFFF;
2135 DWORD disable = 0x00000000;
2137 /* If enabling / disabling all */
2138 if (State == D3DRS_CLIPPING) {
2139 if (Value) {
2140 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2141 disable = 0x00;
2142 } else {
2143 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2144 enable = 0x00;
2146 } else {
2147 enable = Value & ~OldValue;
2148 disable = ~Value & OldValue;
2151 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2152 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2153 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2154 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2155 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2156 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2158 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2159 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2160 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2161 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2162 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2163 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2165 break;
2167 case D3DRS_BLENDOP :
2169 int glParm = GL_FUNC_ADD;
2171 switch ((D3DBLENDOP) Value) {
2172 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2173 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2174 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2175 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2176 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2177 default:
2178 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2180 TRACE("glBlendEquation(%x)\n", glParm);
2181 glBlendEquation(glParm);
2182 checkGLcall("glBlendEquation");
2184 break;
2186 case D3DRS_TEXTUREFACTOR :
2188 int i;
2190 /* Note the texture color applies to all textures whereas
2191 GL_TEXTURE_ENV_COLOR applies to active only */
2192 float col[4];
2193 D3DCOLORTOGLFLOAT4(Value, col);
2194 /* Set the default alpha blend color */
2195 glBlendColor(col[0], col[1], col[2], col[3]);
2196 checkGLcall("glBlendColor");
2198 /* And now the default texture color as well */
2199 for (i = 0; i < GL_LIMITS(textures); i++) {
2201 /* Note the D3DRS value applies to all textures, but GL has one
2202 per texture, so apply it now ready to be used! */
2203 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2204 #if defined(GL_VERSION_1_3)
2205 glActiveTexture(GL_TEXTURE0 + i);
2206 #else
2207 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2208 #endif
2209 checkGLcall("Activate texture.. to update const color");
2210 } else if (i>0) {
2211 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2214 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2215 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2218 break;
2220 case D3DRS_SPECULARENABLE :
2222 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2223 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2224 specular color. This is wrong:
2225 Seperate specular color means the specular colour is maintained seperately, whereas
2226 single color means it is merged in. However in both cases they are being used to
2227 some extent.
2228 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2229 NOTE: If not supported dont give FIXME as very minimal impact and very few people are
2230 yet running 1.4!
2232 if (Value) {
2233 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2234 checkGLcall("glMaterialfv");
2235 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2236 glEnable(GL_COLOR_SUM_EXT);
2237 } else {
2238 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2240 checkGLcall("glEnable(GL_COLOR_SUM)\n");
2241 } else {
2242 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2244 /* for the case of enabled lighting: */
2245 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2246 checkGLcall("glMaterialfv");
2248 /* for the case of disabled lighting: */
2249 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2250 glDisable(GL_COLOR_SUM_EXT);
2251 } else {
2252 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2254 checkGLcall("glDisable(GL_COLOR_SUM)\n");
2257 break;
2259 case D3DRS_STENCILENABLE :
2260 if (Value) {
2261 glEnable(GL_STENCIL_TEST);
2262 checkGLcall("glEnable GL_STENCIL_TEST");
2263 } else {
2264 glDisable(GL_STENCIL_TEST);
2265 checkGLcall("glDisable GL_STENCIL_TEST");
2267 break;
2269 case D3DRS_STENCILFUNC :
2271 int glParm = GL_ALWAYS;
2272 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2273 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2275 switch ((D3DCMPFUNC) Value) {
2276 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2277 case D3DCMP_LESS: glParm=GL_LESS; break;
2278 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2279 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2280 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2281 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2282 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2283 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2284 default:
2285 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2287 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2288 This->stencilfunc = glParm;
2289 glStencilFunc(glParm, ref, mask);
2290 checkGLcall("glStencilFunc");
2292 break;
2294 case D3DRS_STENCILREF :
2296 int glParm = This->stencilfunc;
2297 int ref = 0;
2298 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2300 ref = Value;
2301 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2302 glStencilFunc(glParm, ref, mask);
2303 checkGLcall("glStencilFunc");
2305 break;
2307 case D3DRS_STENCILMASK :
2309 int glParm = This->stencilfunc;
2310 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2311 GLuint mask = Value;
2313 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2314 glStencilFunc(glParm, ref, mask);
2315 checkGLcall("glStencilFunc");
2317 break;
2319 case D3DRS_STENCILFAIL :
2321 GLenum fail ;
2322 GLenum zpass ;
2323 GLenum zfail ;
2325 fail = StencilOp(Value);
2326 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2327 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2328 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2329 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2331 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2332 glStencilOp(fail, zfail, zpass);
2333 checkGLcall("glStencilOp(fail, zfail, zpass);");
2335 break;
2336 case D3DRS_STENCILZFAIL :
2338 GLenum fail ;
2339 GLenum zpass ;
2340 GLenum zfail ;
2342 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2343 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2344 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2345 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2346 zfail = StencilOp(Value);
2348 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2349 glStencilOp(fail, zfail, zpass);
2350 checkGLcall("glStencilOp(fail, zfail, zpass);");
2352 break;
2353 case D3DRS_STENCILPASS :
2355 GLenum fail ;
2356 GLenum zpass ;
2357 GLenum zfail ;
2359 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2360 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2361 zpass = StencilOp(Value);
2362 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2363 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2365 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2366 glStencilOp(fail, zfail, zpass);
2367 checkGLcall("glStencilOp(fail, zfail, zpass);");
2369 break;
2371 case D3DRS_STENCILWRITEMASK :
2373 glStencilMask(Value);
2374 TRACE("glStencilMask(%lu)\n", Value);
2375 checkGLcall("glStencilMask");
2377 break;
2379 case D3DRS_FOGENABLE :
2381 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2382 glEnable(GL_FOG);
2383 checkGLcall("glEnable GL_FOG\n");
2384 } else {
2385 glDisable(GL_FOG);
2386 checkGLcall("glDisable GL_FOG\n");
2389 break;
2391 case D3DRS_FOGCOLOR :
2393 float col[4];
2394 D3DCOLORTOGLFLOAT4(Value, col);
2395 /* Set the default alpha blend color */
2396 glFogfv(GL_FOG_COLOR, &col[0]);
2397 checkGLcall("glFog GL_FOG_COLOR");
2399 break;
2401 case D3DRS_FOGTABLEMODE :
2403 switch (Value) {
2404 case D3DFOG_NONE: /* I don't know what to do here */ break;
2405 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2406 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2407 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2408 default:
2409 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2412 break;
2414 case D3DRS_FOGSTART :
2416 float *f = (float*) &Value;
2417 glFogfv(GL_FOG_START, f);
2418 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2419 TRACE("Fog Start == %f\n", *f);
2421 break;
2423 case D3DRS_FOGEND :
2425 float *f = (float*) &Value;
2426 glFogfv(GL_FOG_END, f);
2427 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2428 TRACE("Fog End == %f\n", *f);
2430 break;
2432 case D3DRS_FOGDENSITY :
2434 float *f = (float*) &Value;
2435 glFogfv(GL_FOG_DENSITY, f);
2436 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2438 break;
2440 case D3DRS_VERTEXBLEND :
2442 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2443 TRACE("Vertex Blending state to %ld\n", Value);
2445 break;
2447 case D3DRS_TWEENFACTOR :
2449 This->UpdateStateBlock->tween_factor = *((float*) &Value);
2450 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2452 break;
2454 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2456 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2458 break;
2460 case D3DRS_COLORVERTEX :
2461 case D3DRS_DIFFUSEMATERIALSOURCE :
2462 case D3DRS_SPECULARMATERIALSOURCE :
2463 case D3DRS_AMBIENTMATERIALSOURCE :
2464 case D3DRS_EMISSIVEMATERIALSOURCE :
2466 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2468 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2469 glEnable(GL_COLOR_MATERIAL);
2470 checkGLcall("glEnable GL_GL_COLOR_MATERIAL\n");
2472 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2473 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2474 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2475 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2476 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2478 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2479 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2480 Parm = GL_AMBIENT_AND_DIFFUSE;
2481 } else {
2482 Parm = GL_DIFFUSE;
2484 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2485 Parm = GL_AMBIENT;
2486 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2487 Parm = GL_EMISSION;
2488 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2489 Parm = GL_SPECULAR;
2490 } else {
2491 Parm = -1;
2494 if (Parm == -1) {
2495 glDisable(GL_COLOR_MATERIAL);
2496 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
2497 } else {
2498 TRACE("glColorMaterial Parm=%d\n", Parm);
2499 glColorMaterial(GL_FRONT_AND_BACK, Parm);
2500 checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)\n");
2503 } else {
2504 glDisable(GL_COLOR_MATERIAL);
2505 checkGLcall("glDisable GL_GL_COLOR_MATERIAL\n");
2508 break;
2510 case D3DRS_LINEPATTERN :
2512 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2513 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2515 if (pattern->wRepeatFactor) {
2516 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2517 checkGLcall("glLineStipple(repeat, linepattern)\n");
2518 glEnable(GL_LINE_STIPPLE);
2519 checkGLcall("glEnable(GL_LINE_STIPPLE);\n");
2520 } else {
2521 glDisable(GL_LINE_STIPPLE);
2522 checkGLcall("glDisable(GL_LINE_STIPPLE);\n");
2525 break;
2527 case D3DRS_ZBIAS :
2529 if (Value) {
2530 TRACE("ZBias value %f\n", *((float*)&Value));
2531 glPolygonOffset(0, -*((float*)&Value));
2532 checkGLcall("glPolygonOffset(0, -Value)");
2533 glEnable(GL_POLYGON_OFFSET_FILL);
2534 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2535 glEnable(GL_POLYGON_OFFSET_LINE);
2536 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2537 glEnable(GL_POLYGON_OFFSET_POINT);
2538 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2539 } else {
2540 glDisable(GL_POLYGON_OFFSET_FILL);
2541 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2542 glDisable(GL_POLYGON_OFFSET_LINE);
2543 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2544 glDisable(GL_POLYGON_OFFSET_POINT);
2545 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2548 break;
2550 case D3DRS_NORMALIZENORMALS :
2551 if (Value) {
2552 glEnable(GL_NORMALIZE);
2553 checkGLcall("glEnable(GL_NORMALIZE);");
2554 } else {
2555 glDisable(GL_NORMALIZE);
2556 checkGLcall("glDisable(GL_NORMALIZE);");
2558 break;
2560 case D3DRS_POINTSIZE :
2561 TRACE("Set point size to %f\n", *((float*)&Value));
2562 glPointSize(*((float*)&Value));
2563 checkGLcall("glPointSize(...);\n");
2564 break;
2566 case D3DRS_POINTSIZE_MIN :
2567 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2568 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2569 checkGLcall("glPointParameterfEXT(...);\n");
2570 } else {
2571 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2573 break;
2575 case D3DRS_POINTSIZE_MAX :
2576 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2577 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2578 checkGLcall("glPointParameterfEXT(...);\n");
2579 } else {
2580 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2582 break;
2584 case D3DRS_POINTSCALE_A :
2585 case D3DRS_POINTSCALE_B :
2586 case D3DRS_POINTSCALE_C :
2587 case D3DRS_POINTSCALEENABLE :
2589 /* If enabled, supply the parameters, otherwise fall back to defaults */
2590 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2591 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2592 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2593 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2594 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2596 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2597 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2598 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);\n");
2599 } else {
2600 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2602 } else {
2603 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2604 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2605 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2606 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);\n");
2607 } else {
2608 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2611 break;
2614 case D3DRS_COLORWRITEENABLE :
2615 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2616 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2617 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2618 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2619 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2620 glColorMask(Value & D3DCOLORWRITEENABLE_RED,
2621 Value & D3DCOLORWRITEENABLE_GREEN,
2622 Value & D3DCOLORWRITEENABLE_BLUE,
2623 Value & D3DCOLORWRITEENABLE_ALPHA);
2624 checkGLcall("glColorMask(...)\n");
2625 break;
2627 /* Unhandled yet...! */
2628 case D3DRS_LASTPIXEL :
2629 case D3DRS_ZVISIBLE :
2630 case D3DRS_EDGEANTIALIAS :
2631 case D3DRS_RANGEFOGENABLE :
2632 case D3DRS_WRAP0 :
2633 case D3DRS_WRAP1 :
2634 case D3DRS_WRAP2 :
2635 case D3DRS_WRAP3 :
2636 case D3DRS_WRAP4 :
2637 case D3DRS_WRAP5 :
2638 case D3DRS_WRAP6 :
2639 case D3DRS_WRAP7 :
2640 case D3DRS_FOGVERTEXMODE :
2641 case D3DRS_LOCALVIEWER :
2642 case D3DRS_SOFTWAREVERTEXPROCESSING :
2643 case D3DRS_POINTSPRITEENABLE :
2644 case D3DRS_MULTISAMPLEANTIALIAS :
2645 case D3DRS_MULTISAMPLEMASK :
2646 case D3DRS_PATCHEDGESTYLE :
2647 case D3DRS_PATCHSEGMENTS :
2648 case D3DRS_DEBUGMONITORTOKEN :
2649 case D3DRS_POSITIONORDER :
2650 case D3DRS_NORMALORDER :
2651 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2652 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2653 break;
2654 default:
2655 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2658 return D3D_OK;
2660 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2661 ICOM_THIS(IDirect3DDevice8Impl,iface);
2662 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2663 *pValue = This->StateBlock->renderstate[State];
2664 return D3D_OK;
2666 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2667 ICOM_THIS(IDirect3DDevice8Impl,iface);
2669 TRACE("(%p)\n", This);
2671 return IDirect3DDeviceImpl_BeginStateBlock(This);
2673 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2674 IDirect3DStateBlockImpl* pSB;
2675 ICOM_THIS(IDirect3DDevice8Impl,iface);
2676 HRESULT res;
2678 TRACE("(%p)\n", This);
2680 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2681 *pToken = (DWORD) pSB;
2682 return res;
2685 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2686 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2687 ICOM_THIS(IDirect3DDevice8Impl,iface);
2689 TRACE("(%p)\n", This);
2691 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2694 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2695 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2696 ICOM_THIS(IDirect3DDevice8Impl,iface);
2698 TRACE("(%p)\n", This);
2700 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2702 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2703 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2704 ICOM_THIS(IDirect3DDevice8Impl,iface);
2706 TRACE("(%p)\n", This);
2708 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
2711 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
2712 IDirect3DStateBlockImpl* pSB;
2713 ICOM_THIS(IDirect3DDevice8Impl,iface);
2714 HRESULT res;
2716 TRACE("(%p) : for type %d\n", This, Type);
2718 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
2719 *pToken = (DWORD) pSB;
2720 return res;
2723 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
2724 ICOM_THIS(IDirect3DDevice8Impl,iface);
2725 FIXME("(%p) : stub\n", This); return D3D_OK;
2727 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
2728 ICOM_THIS(IDirect3DDevice8Impl,iface);
2729 FIXME("(%p) : stub\n", This); return D3D_OK;
2731 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
2732 ICOM_THIS(IDirect3DDevice8Impl,iface);
2733 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
2734 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
2735 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
2736 return D3D_OK;
2738 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
2740 IDirect3DBaseTexture8 *oldTxt;
2741 BOOL reapplyStates = TRUE;
2743 ICOM_THIS(IDirect3DDevice8Impl,iface);
2744 D3DRESOURCETYPE textureType;
2746 oldTxt = This->UpdateStateBlock->textures[Stage];
2747 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
2749 /* Reject invalid texture units */
2750 if (Stage >= GL_LIMITS(textures)) {
2751 TRACE("Attempt to access invalid texture rejected\n");
2752 return D3DERR_INVALIDCALL;
2755 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
2756 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
2757 This->UpdateStateBlock->textures[Stage] = pTexture;
2759 /* Handle recording of state blocks */
2760 if (This->isRecordingState) {
2761 TRACE("Recording... not performing anything\n");
2762 return D3D_OK;
2765 /* Make appropriate texture active */
2766 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2767 #if defined(GL_VERSION_1_3)
2768 glActiveTexture(GL_TEXTURE0 + Stage);
2769 #else
2770 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2771 #endif
2772 checkGLcall("glActiveTextureARB");
2773 } else if (Stage>0) {
2774 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2777 /* Decrement the count of the previous texture */
2778 if (NULL != oldTxt) {
2779 IDirect3DBaseTexture8Impl_Release(oldTxt);
2782 if (NULL != pTexture) {
2783 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
2785 /* Now setup the texture appropraitly */
2786 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
2788 if (textureType == D3DRTYPE_TEXTURE) {
2789 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
2790 TRACE("Skipping setting texture as old == new\n");
2791 reapplyStates = FALSE;
2792 } else {
2793 /* Standard 2D texture */
2794 TRACE("Standard 2d texture\n");
2795 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
2797 /* Load up the texture now */
2798 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
2800 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
2801 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
2802 TRACE("Skipping setting texture as old == new\n");
2803 reapplyStates = FALSE;
2804 } else {
2805 /* Standard 3D (volume) texture */
2806 TRACE("Standard 3d texture\n");
2807 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
2809 /* Load up the texture now */
2810 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
2812 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
2813 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
2814 TRACE("Skipping setting texture as old == new\n");
2815 reapplyStates = FALSE;
2816 } else {
2817 /* Standard Cube texture */
2818 TRACE("Standard Cube texture\n");
2819 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
2821 /* Load up the texture now */
2822 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
2824 } else {
2825 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
2827 } else {
2828 TRACE("Setting to no texture (ie default texture)\n");
2829 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
2830 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
2831 checkGLcall("glBindTexture");
2832 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
2835 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
2836 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
2837 if (reapplyStates) {
2838 setupTextureStates(iface, Stage);
2841 return D3D_OK;
2844 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
2845 ICOM_THIS(IDirect3DDevice8Impl,iface);
2846 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
2847 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
2848 return D3D_OK;
2851 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
2852 ICOM_THIS(IDirect3DDevice8Impl,iface);
2854 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
2856 TRACE("(%p) : stub, Stage=%ld, Type=%d, Value=%ld\n", This, Stage, Type, Value);
2858 /* Reject invalid texture units */
2859 if (Stage >= GL_LIMITS(textures)) {
2860 TRACE("Attempt to access invalid texture rejected\n");
2861 return D3DERR_INVALIDCALL;
2864 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
2865 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
2866 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
2868 /* Handle recording of state blocks */
2869 if (This->isRecordingState) {
2870 TRACE("Recording... not performing anything\n");
2871 return D3D_OK;
2874 /* Make appropriate texture active */
2875 VTRACE(("Activating appropriate texture state %ld\n", Stage));
2876 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2877 #if defined(GL_VERSION_1_3)
2878 glActiveTexture(GL_TEXTURE0 + Stage);
2879 vcheckGLcall("glActiveTexture");
2880 #else
2881 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2882 vcheckGLcall("glActiveTextureARB");
2883 #endif
2884 } else if (Stage > 0) {
2885 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2888 switch (Type) {
2890 case D3DTSS_MINFILTER :
2891 case D3DTSS_MIPFILTER :
2893 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
2894 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
2895 GLint realVal = GL_LINEAR;
2897 if (ValueMIN == D3DTEXF_POINT) {
2898 /* GL_NEAREST_* */
2899 if (ValueMIP == D3DTEXF_POINT) {
2900 realVal = GL_NEAREST_MIPMAP_NEAREST;
2901 } else if (ValueMIP == D3DTEXF_LINEAR) {
2902 realVal = GL_NEAREST_MIPMAP_LINEAR;
2903 } else if (ValueMIP == D3DTEXF_NONE) {
2904 realVal = GL_NEAREST;
2905 } else {
2906 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2907 realVal = GL_NEAREST_MIPMAP_LINEAR;
2909 } else if (ValueMIN == D3DTEXF_LINEAR) {
2910 /* GL_LINEAR_* */
2911 if (ValueMIP == D3DTEXF_POINT) {
2912 realVal = GL_LINEAR_MIPMAP_NEAREST;
2913 } else if (ValueMIP == D3DTEXF_LINEAR) {
2914 realVal = GL_LINEAR_MIPMAP_LINEAR;
2915 } else if (ValueMIP == D3DTEXF_NONE) {
2916 realVal = GL_LINEAR;
2917 } else {
2918 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2919 realVal = GL_LINEAR_MIPMAP_LINEAR;
2921 } else if (ValueMIN == D3DTEXF_NONE) {
2922 /* Doesnt really make sense - Windows just seems to disable
2923 mipmapping when this occurs */
2924 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
2925 realVal = GL_LINEAR;
2927 } else {
2928 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
2929 realVal = GL_LINEAR_MIPMAP_LINEAR;
2932 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
2933 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
2934 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
2936 break;
2938 case D3DTSS_MAXANISOTROPY :
2940 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2941 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
2942 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
2945 break;
2947 case D3DTSS_MAGFILTER :
2948 if (Value == D3DTEXF_POINT) {
2949 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2950 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
2951 } else if (Value == D3DTEXF_LINEAR) {
2952 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2953 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
2954 } else {
2955 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
2957 break;
2959 case D3DTSS_ALPHAOP :
2960 case D3DTSS_COLOROP :
2963 if (Value == D3DTOP_DISABLE) {
2964 /* TODO: Disable by making this and all later levels disabled */
2965 if (Type == D3DTSS_COLOROP) {
2966 glDisable(GL_TEXTURE_1D);
2967 checkGLcall("Disable GL_TEXTURE_1D");
2968 glDisable(GL_TEXTURE_2D);
2969 checkGLcall("Disable GL_TEXTURE_2D");
2970 glDisable(GL_TEXTURE_3D);
2971 checkGLcall("Disable GL_TEXTURE_3D");
2973 break; /* Dont bother setting the texture operations */
2974 } else {
2975 /* Enable only the appropriate texture dimension */
2976 if (Type == D3DTSS_COLOROP) {
2977 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2978 glEnable(GL_TEXTURE_1D);
2979 checkGLcall("Enable GL_TEXTURE_1D");
2980 } else {
2981 glDisable(GL_TEXTURE_1D);
2982 checkGLcall("Disable GL_TEXTURE_1D");
2984 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
2985 glEnable(GL_TEXTURE_2D);
2986 checkGLcall("Enable GL_TEXTURE_2D");
2987 } else {
2988 glDisable(GL_TEXTURE_2D);
2989 checkGLcall("Disable GL_TEXTURE_2D");
2991 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
2992 glEnable(GL_TEXTURE_3D);
2993 checkGLcall("Enable GL_TEXTURE_3D");
2994 } else {
2995 glDisable(GL_TEXTURE_3D);
2996 checkGLcall("Disable GL_TEXTURE_3D");
2998 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
2999 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3000 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3001 } else {
3002 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3003 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3007 /* Drop through... (Except disable case) */
3008 case D3DTSS_COLORARG0 :
3009 case D3DTSS_COLORARG1 :
3010 case D3DTSS_COLORARG2 :
3011 case D3DTSS_ALPHAARG0 :
3012 case D3DTSS_ALPHAARG1 :
3013 case D3DTSS_ALPHAARG2 :
3015 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3016 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3017 if (isAlphaArg) {
3018 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3019 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3020 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3021 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3022 } else {
3023 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3024 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3025 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3026 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3029 break;
3032 case D3DTSS_ADDRESSU :
3033 case D3DTSS_ADDRESSV :
3034 case D3DTSS_ADDRESSW :
3036 GLint wrapParm = GL_REPEAT;
3037 switch (Value) {
3038 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3039 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3040 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3041 #if defined(GL_VERSION_1_4)
3042 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3043 #elif defined(GL_ARB_texture_mirrored_repeat)
3044 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3045 #else
3046 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3047 #endif
3048 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3049 default:
3050 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3051 wrapParm = GL_REPEAT;
3054 switch (Type) {
3055 case D3DTSS_ADDRESSU:
3056 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3057 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3058 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3059 break;
3060 case D3DTSS_ADDRESSV:
3061 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3062 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3063 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3064 break;
3065 case D3DTSS_ADDRESSW:
3066 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3067 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3068 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3069 break;
3070 default: /* nop */
3071 break; /** stupic compilator */
3074 break;
3076 case D3DTSS_BORDERCOLOR :
3078 float col[4];
3079 D3DCOLORTOGLFLOAT4(Value, col);
3080 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3081 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3082 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3084 break;
3086 case D3DTSS_TEXCOORDINDEX :
3088 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3090 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3091 one flag, you can still specify an index value, which the system uses to
3092 determine the texture wrapping mode.
3093 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3094 means use the vertex position (camera-space) as the input texture coordinates
3095 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3096 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3097 to the TEXCOORDINDEX value */
3099 /**
3100 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3102 switch (Value & 0xFFFF0000) {
3103 case D3DTSS_TCI_PASSTHRU:
3104 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3105 glDisable(GL_TEXTURE_GEN_S);
3106 glDisable(GL_TEXTURE_GEN_T);
3107 glDisable(GL_TEXTURE_GEN_R);
3108 break;
3110 case D3DTSS_TCI_CAMERASPACEPOSITION:
3111 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3112 as the input texture coordinates for this stage's texture transformation. This
3113 equates roughly to EYE_LINEAR */
3115 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3116 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3117 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3118 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3119 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3121 glMatrixMode(GL_MODELVIEW);
3122 glPushMatrix();
3123 glLoadIdentity();
3124 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3125 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3126 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3127 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3128 glPopMatrix();
3130 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3131 glEnable(GL_TEXTURE_GEN_S);
3132 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3133 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3134 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3135 glEnable(GL_TEXTURE_GEN_T);
3136 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3137 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3138 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3139 glEnable(GL_TEXTURE_GEN_R);
3140 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3141 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3142 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3144 break;
3146 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3147 case D3DTSS_TCI_CAMERASPACENORMAL:
3149 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3150 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3151 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3152 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3153 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3155 glMatrixMode(GL_MODELVIEW);
3156 glPushMatrix();
3157 glLoadIdentity();
3158 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3159 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3160 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3161 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3162 glPopMatrix();
3164 glEnable(GL_TEXTURE_GEN_S);
3165 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3166 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3167 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3168 glEnable(GL_TEXTURE_GEN_T);
3169 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3170 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3171 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3172 glEnable(GL_TEXTURE_GEN_R);
3173 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3174 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3175 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3177 break;
3178 #endif
3180 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3181 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3184 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3185 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3186 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3187 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3188 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3190 glMatrixMode(GL_MODELVIEW);
3191 glPushMatrix();
3192 glLoadIdentity();
3193 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3194 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3195 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3196 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3197 glPopMatrix();
3199 glEnable(GL_TEXTURE_GEN_S);
3200 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3201 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3202 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3203 glEnable(GL_TEXTURE_GEN_T);
3204 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3205 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3206 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3207 glEnable(GL_TEXTURE_GEN_R);
3208 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3209 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3210 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3212 break;
3213 #endif
3215 /* Unhandled types: */
3216 default:
3217 /* Todo: */
3218 /* ? disable GL_TEXTURE_GEN_n ? */
3219 glDisable(GL_TEXTURE_GEN_S);
3220 glDisable(GL_TEXTURE_GEN_T);
3221 glDisable(GL_TEXTURE_GEN_R);
3222 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3223 break;
3226 break;
3228 /* Unhandled */
3229 case D3DTSS_BUMPENVMAT00 :
3230 case D3DTSS_BUMPENVMAT01 :
3231 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3232 break;
3233 case D3DTSS_BUMPENVMAT10 :
3234 case D3DTSS_BUMPENVMAT11 :
3235 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3236 break;
3238 case D3DTSS_TEXTURETRANSFORMFLAGS :
3240 switch (Value & ~D3DTTFF_PROJECTED)
3242 case D3DTTFF_DISABLE: /* Disable transform matrix for this texture by setting up the identity matrix */
3243 glMatrixMode(GL_TEXTURE);
3244 glLoadIdentity();
3245 checkGLcall("Load identity matrix for texture");
3246 glMatrixMode(GL_MODELVIEW); /* Always leave in model view */
3247 break;
3249 default: /* Enable it */
3250 IDirect3DDevice8Impl_SetTransform(iface, D3DTS_TEXTURE0+Stage, &This->UpdateStateBlock->transforms[D3DTS_TEXTURE0+Stage]);
3251 break;
3254 /* From web: <quote source="opengl12.pdf" section="Apendix C, Version 1.1/Other changes"
3255 2. Texture coordinates s, t, and r are divided by q during the rasterization
3256 of points, pixel rectangles, and bitmaps. This division was documented
3257 only for lines and polygons in the 1.0 version. </quote>
3258 I interpret this as we can implement projected transforms in slow vertex mode
3259 by moving the last coord to the 'q' coord and using one less dimension. The only
3260 way to do it in TexCoordPtr would be to massage the data stream to insert extra
3261 coords */
3263 break;
3265 case D3DTSS_MIPMAPLODBIAS :
3266 case D3DTSS_MAXMIPLEVEL :
3267 case D3DTSS_BUMPENVLSCALE :
3268 case D3DTSS_BUMPENVLOFFSET :
3269 case D3DTSS_RESULTARG :
3270 default:
3271 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3272 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3274 return D3D_OK;
3276 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3277 ICOM_THIS(IDirect3DDevice8Impl,iface);
3278 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3279 return D3D_OK;
3281 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3282 ICOM_THIS(IDirect3DDevice8Impl,iface);
3283 FIXME("(%p) : stub\n", This);
3284 return D3D_OK;
3286 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3287 ICOM_THIS(IDirect3DDevice8Impl,iface);
3288 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3289 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3290 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3291 return D3D_OK;
3293 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3294 ICOM_THIS(IDirect3DDevice8Impl,iface);
3295 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3296 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3297 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3298 return D3D_OK;
3300 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3301 ICOM_THIS(IDirect3DDevice8Impl,iface);
3302 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3303 This->currentPalette = PaletteNumber;
3304 #if defined(GL_EXT_paletted_texture)
3305 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3306 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3307 GL_RGBA, /* internal format */
3308 256, /* table size */
3309 GL_RGBA, /* table format */
3310 GL_UNSIGNED_BYTE, /* table type */
3311 This->palettes[PaletteNumber]);
3312 checkGLcall("glColorTableEXT");
3313 } else {
3314 /* Delayed palette handling ... waiting for software emulation into preload code */
3316 #endif
3317 return D3D_OK;
3319 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3320 ICOM_THIS(IDirect3DDevice8Impl,iface);
3321 *PaletteNumber = This->currentPalette;
3322 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3323 return D3D_OK;
3325 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3327 ICOM_THIS(IDirect3DDevice8Impl,iface);
3328 This->StateBlock->streamIsUP = FALSE;
3330 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3331 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3333 return D3D_OK;
3335 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3336 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3337 UINT idxStride = 2;
3338 IDirect3DIndexBuffer8 *pIB;
3339 D3DINDEXBUFFER_DESC IdxBufDsc;
3341 ICOM_THIS(IDirect3DDevice8Impl,iface);
3342 pIB = This->StateBlock->pIndexData;
3343 This->StateBlock->streamIsUP = FALSE;
3345 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3346 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3347 minIndex, NumVertices, startIndex, primCount);
3349 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3350 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3351 idxStride = 2;
3352 } else {
3353 idxStride = 4;
3356 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3357 minIndex);
3359 return D3D_OK;
3361 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3362 ICOM_THIS(IDirect3DDevice8Impl,iface);
3364 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3365 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3367 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3369 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3370 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3371 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3372 This->StateBlock->streamIsUP = TRUE;
3373 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3374 This->StateBlock->stream_stride[0] = 0;
3375 This->StateBlock->stream_source[0] = NULL;
3377 /*stream zero settings set to null at end */
3378 return D3D_OK;
3380 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3381 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3382 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3383 UINT VertexStreamZeroStride) {
3384 int idxStride;
3385 ICOM_THIS(IDirect3DDevice8Impl,iface);
3386 TRACE("(%p) : Type=(%d,%s), MinVtxIdx=%d, NumVIdx=%d, PCount=%d, pidxdata=%p, IdxFmt=%d, pVtxdata=%p, stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3387 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3389 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3390 if (IndexDataFormat == D3DFMT_INDEX16) {
3391 idxStride = 2;
3392 } else {
3393 idxStride = 4;
3396 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3397 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3398 This->StateBlock->streamIsUP = TRUE;
3399 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3400 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3402 /*stream zero settings set to null at end */
3403 This->StateBlock->stream_source[0] = NULL;
3404 This->StateBlock->stream_stride[0] = 0;
3405 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3407 return D3D_OK;
3409 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3410 ICOM_THIS(IDirect3DDevice8Impl,iface);
3411 FIXME("(%p) : stub\n", This); return D3D_OK;
3413 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3414 ICOM_THIS(IDirect3DDevice8Impl,iface);
3415 IDirect3DVertexShaderImpl* object;
3416 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3417 HRESULT res;
3418 UINT i;
3420 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p\n", This, pDeclaration, pFunction);
3421 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3422 return D3DERR_INVALIDCALL;
3424 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3425 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3426 return D3DERR_OUTOFVIDEOMEMORY;
3429 /** Create the Vertex Shader */
3430 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3431 /** TODO: check FAILED(res) */
3433 /** Create and Bind the Vertex Shader Declaration */
3434 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3435 /** TODO: check FAILED(res) */
3437 VertexShaders[i] = object;
3438 VertexShaderDeclarations[i] = attached_decl;
3439 *pHandle = VS_HIGHESTFIXEDFXF + i;
3440 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3442 return D3D_OK;
3444 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3445 ICOM_THIS(IDirect3DDevice8Impl,iface);
3447 This->UpdateStateBlock->VertexShader = Handle;
3448 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3449 This->UpdateStateBlock->Set.vertexShader = TRUE;
3451 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3452 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3453 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3454 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3455 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3456 } else { /* use a fvf, so desactivate the vshader decl */
3457 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3458 This->UpdateStateBlock->vertexShaderDecl = NULL;
3459 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3460 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3462 /* Handle recording of state blocks */
3463 if (This->isRecordingState) {
3464 TRACE("Recording... not performing anything\n");
3465 return D3D_OK;
3468 * TODO: merge HAL shaders context switching from prototype
3470 return D3D_OK;
3472 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3473 ICOM_THIS(IDirect3DDevice8Impl,iface);
3474 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3475 *pHandle = This->StateBlock->VertexShader;
3476 return D3D_OK;
3479 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3480 ICOM_THIS(IDirect3DDevice8Impl,iface);
3481 IDirect3DVertexShaderImpl* object;
3482 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3484 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3485 return D3DERR_INVALIDCALL;
3489 * Delete Vertex Shader
3491 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3492 if (NULL == object) {
3493 return D3DERR_INVALIDCALL;
3495 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3496 /* TODO: check validity of object */
3497 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3498 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3499 HeapFree(GetProcessHeap(), 0, (void *)object);
3500 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3503 * Delete Vertex Shader Declaration
3505 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3506 if (NULL == attached_decl) {
3507 return D3DERR_INVALIDCALL;
3509 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3510 /* TODO: check validity of object */
3511 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3512 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3513 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3515 return D3D_OK;
3518 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3519 ICOM_THIS(IDirect3DDevice8Impl,iface);
3521 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3522 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3523 return D3DERR_INVALIDCALL;
3525 if (NULL == pConstantData) {
3526 return D3DERR_INVALIDCALL;
3528 if (ConstantCount > 1) {
3529 FLOAT* f = (FLOAT*)pConstantData;
3530 UINT i;
3531 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3532 for (i = 0; i < ConstantCount; ++i) {
3533 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3534 f += 4;
3536 } else {
3537 FLOAT* f = (FLOAT*) pConstantData;
3538 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3540 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3541 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3542 return D3D_OK;
3544 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3545 ICOM_THIS(IDirect3DDevice8Impl,iface);
3547 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3548 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3549 return D3DERR_INVALIDCALL;
3551 if (NULL == pConstantData) {
3552 return D3DERR_INVALIDCALL;
3554 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3555 return D3D_OK;
3557 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3558 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3559 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3561 attached_decl = VERTEX_SHADER_DECL(Handle);
3562 if (NULL == attached_decl) {
3563 return D3DERR_INVALIDCALL;
3565 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3567 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3568 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3569 IDirect3DVertexShaderImpl* object;
3571 object = VERTEX_SHADER(Handle);
3572 if (NULL == object) {
3573 return D3DERR_INVALIDCALL;
3575 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3578 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3579 ICOM_THIS(IDirect3DDevice8Impl,iface);
3580 IDirect3DIndexBuffer8 *oldIdxs;
3582 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3583 oldIdxs = This->StateBlock->pIndexData;
3585 This->UpdateStateBlock->Changed.Indices = TRUE;
3586 This->UpdateStateBlock->Set.Indices = TRUE;
3587 This->UpdateStateBlock->pIndexData = pIndexData;
3588 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3590 /* Handle recording of state blocks */
3591 if (This->isRecordingState) {
3592 TRACE("Recording... not performing anything\n");
3593 return D3D_OK;
3596 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3597 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3598 return D3D_OK;
3600 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3601 ICOM_THIS(IDirect3DDevice8Impl,iface);
3602 FIXME("(%p) : stub\n", This);
3604 *ppIndexData = This->StateBlock->pIndexData;
3605 /* up ref count on ppindexdata */
3606 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3607 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3609 return D3D_OK;
3611 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3612 ICOM_THIS(IDirect3DDevice8Impl,iface);
3613 IDirect3DPixelShaderImpl* object;
3614 HRESULT res;
3615 UINT i;
3617 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3618 if (NULL == pFunction || NULL == pHandle) {
3619 return D3DERR_INVALIDCALL;
3621 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3622 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3623 return D3DERR_OUTOFVIDEOMEMORY;
3626 /** Create the Pixel Shader */
3627 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3628 if (SUCCEEDED(res)) {
3629 PixelShaders[i] = object;
3630 *pHandle = VS_HIGHESTFIXEDFXF + i;
3631 return D3D_OK;
3633 *pHandle = 0xFFFFFFFF;
3634 return res;
3636 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3637 ICOM_THIS(IDirect3DDevice8Impl,iface);
3639 This->UpdateStateBlock->PixelShader = Handle;
3640 This->UpdateStateBlock->Changed.pixelShader = TRUE;
3641 This->UpdateStateBlock->Set.pixelShader = TRUE;
3643 /* Handle recording of state blocks */
3644 if (This->isRecordingState) {
3645 TRACE_(d3d_shader)("Recording... not performing anything\n");
3646 return D3D_OK;
3649 /* FIXME: Quieten when not being used */
3650 if (Handle != 0) {
3651 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3652 } else {
3653 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3656 return D3D_OK;
3658 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3659 ICOM_THIS(IDirect3DDevice8Impl,iface);
3660 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3661 *pHandle = This->StateBlock->PixelShader;
3662 return D3D_OK;
3665 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3666 ICOM_THIS(IDirect3DDevice8Impl,iface);
3667 IDirect3DPixelShaderImpl* object;
3669 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3670 return D3DERR_INVALIDCALL;
3672 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3673 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3674 /* TODO: check validity of object before free */
3675 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3676 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3677 HeapFree(GetProcessHeap(), 0, (void *)object);
3678 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3680 return D3D_OK;
3683 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3684 ICOM_THIS(IDirect3DDevice8Impl,iface);
3686 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
3687 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
3688 return D3DERR_INVALIDCALL;
3690 if (NULL == pConstantData) {
3691 return D3DERR_INVALIDCALL;
3693 if (ConstantCount > 1) {
3694 FLOAT* f = (FLOAT*)pConstantData;
3695 UINT i;
3696 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3697 for (i = 0; i < ConstantCount; ++i) {
3698 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3699 f += 4;
3701 } else {
3702 FLOAT* f = (FLOAT*) pConstantData;
3703 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3705 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
3706 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3707 return D3D_OK;
3709 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3710 ICOM_THIS(IDirect3DDevice8Impl,iface);
3712 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3713 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
3714 return D3DERR_INVALIDCALL;
3716 if (NULL == pConstantData) {
3717 return D3DERR_INVALIDCALL;
3719 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3720 return D3D_OK;
3722 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3723 IDirect3DPixelShaderImpl* object;
3725 object = PIXEL_SHADER(Handle);
3726 if (NULL == object) {
3727 return D3DERR_INVALIDCALL;
3729 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3731 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
3732 ICOM_THIS(IDirect3DDevice8Impl,iface);
3733 FIXME("(%p) : stub\n", This); return D3D_OK;
3735 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
3736 ICOM_THIS(IDirect3DDevice8Impl,iface);
3737 FIXME("(%p) : stub\n", This); return D3D_OK;
3739 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
3740 ICOM_THIS(IDirect3DDevice8Impl,iface);
3741 FIXME("(%p) : stub\n", This); return D3D_OK;
3744 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
3745 IDirect3DVertexBuffer8 *oldSrc;
3746 ICOM_THIS(IDirect3DDevice8Impl,iface);
3748 oldSrc = This->StateBlock->stream_source[StreamNumber];
3749 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
3751 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
3752 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
3753 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
3754 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
3756 /* Handle recording of state blocks */
3757 if (This->isRecordingState) {
3758 TRACE("Recording... not performing anything\n");
3759 return D3D_OK;
3762 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
3763 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
3764 return D3D_OK;
3766 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
3767 ICOM_THIS(IDirect3DDevice8Impl,iface);
3768 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
3769 *pStream = This->StateBlock->stream_source[StreamNumber];
3770 *pStride = This->StateBlock->stream_stride[StreamNumber];
3771 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
3772 return D3D_OK;
3776 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
3778 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3779 IDirect3DDevice8Impl_QueryInterface,
3780 IDirect3DDevice8Impl_AddRef,
3781 IDirect3DDevice8Impl_Release,
3782 IDirect3DDevice8Impl_TestCooperativeLevel,
3783 IDirect3DDevice8Impl_GetAvailableTextureMem,
3784 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
3785 IDirect3DDevice8Impl_GetDirect3D,
3786 IDirect3DDevice8Impl_GetDeviceCaps,
3787 IDirect3DDevice8Impl_GetDisplayMode,
3788 IDirect3DDevice8Impl_GetCreationParameters,
3789 IDirect3DDevice8Impl_SetCursorProperties,
3790 IDirect3DDevice8Impl_SetCursorPosition,
3791 IDirect3DDevice8Impl_ShowCursor,
3792 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
3793 IDirect3DDevice8Impl_Reset,
3794 IDirect3DDevice8Impl_Present,
3795 IDirect3DDevice8Impl_GetBackBuffer,
3796 IDirect3DDevice8Impl_GetRasterStatus,
3797 IDirect3DDevice8Impl_SetGammaRamp,
3798 IDirect3DDevice8Impl_GetGammaRamp,
3799 IDirect3DDevice8Impl_CreateTexture,
3800 IDirect3DDevice8Impl_CreateVolumeTexture,
3801 IDirect3DDevice8Impl_CreateCubeTexture,
3802 IDirect3DDevice8Impl_CreateVertexBuffer,
3803 IDirect3DDevice8Impl_CreateIndexBuffer,
3804 IDirect3DDevice8Impl_CreateRenderTarget,
3805 IDirect3DDevice8Impl_CreateDepthStencilSurface,
3806 IDirect3DDevice8Impl_CreateImageSurface,
3807 IDirect3DDevice8Impl_CopyRects,
3808 IDirect3DDevice8Impl_UpdateTexture,
3809 IDirect3DDevice8Impl_GetFrontBuffer,
3810 IDirect3DDevice8Impl_SetRenderTarget,
3811 IDirect3DDevice8Impl_GetRenderTarget,
3812 IDirect3DDevice8Impl_GetDepthStencilSurface,
3813 IDirect3DDevice8Impl_BeginScene,
3814 IDirect3DDevice8Impl_EndScene,
3815 IDirect3DDevice8Impl_Clear,
3816 IDirect3DDevice8Impl_SetTransform,
3817 IDirect3DDevice8Impl_GetTransform,
3818 IDirect3DDevice8Impl_MultiplyTransform,
3819 IDirect3DDevice8Impl_SetViewport,
3820 IDirect3DDevice8Impl_GetViewport,
3821 IDirect3DDevice8Impl_SetMaterial,
3822 IDirect3DDevice8Impl_GetMaterial,
3823 IDirect3DDevice8Impl_SetLight,
3824 IDirect3DDevice8Impl_GetLight,
3825 IDirect3DDevice8Impl_LightEnable,
3826 IDirect3DDevice8Impl_GetLightEnable,
3827 IDirect3DDevice8Impl_SetClipPlane,
3828 IDirect3DDevice8Impl_GetClipPlane,
3829 IDirect3DDevice8Impl_SetRenderState,
3830 IDirect3DDevice8Impl_GetRenderState,
3831 IDirect3DDevice8Impl_BeginStateBlock,
3832 IDirect3DDevice8Impl_EndStateBlock,
3833 IDirect3DDevice8Impl_ApplyStateBlock,
3834 IDirect3DDevice8Impl_CaptureStateBlock,
3835 IDirect3DDevice8Impl_DeleteStateBlock,
3836 IDirect3DDevice8Impl_CreateStateBlock,
3837 IDirect3DDevice8Impl_SetClipStatus,
3838 IDirect3DDevice8Impl_GetClipStatus,
3839 IDirect3DDevice8Impl_GetTexture,
3840 IDirect3DDevice8Impl_SetTexture,
3841 IDirect3DDevice8Impl_GetTextureStageState,
3842 IDirect3DDevice8Impl_SetTextureStageState,
3843 IDirect3DDevice8Impl_ValidateDevice,
3844 IDirect3DDevice8Impl_GetInfo,
3845 IDirect3DDevice8Impl_SetPaletteEntries,
3846 IDirect3DDevice8Impl_GetPaletteEntries,
3847 IDirect3DDevice8Impl_SetCurrentTexturePalette,
3848 IDirect3DDevice8Impl_GetCurrentTexturePalette,
3849 IDirect3DDevice8Impl_DrawPrimitive,
3850 IDirect3DDevice8Impl_DrawIndexedPrimitive,
3851 IDirect3DDevice8Impl_DrawPrimitiveUP,
3852 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
3853 IDirect3DDevice8Impl_ProcessVertices,
3854 IDirect3DDevice8Impl_CreateVertexShader,
3855 IDirect3DDevice8Impl_SetVertexShader,
3856 IDirect3DDevice8Impl_GetVertexShader,
3857 IDirect3DDevice8Impl_DeleteVertexShader,
3858 IDirect3DDevice8Impl_SetVertexShaderConstant,
3859 IDirect3DDevice8Impl_GetVertexShaderConstant,
3860 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
3861 IDirect3DDevice8Impl_GetVertexShaderFunction,
3862 IDirect3DDevice8Impl_SetStreamSource,
3863 IDirect3DDevice8Impl_GetStreamSource,
3864 IDirect3DDevice8Impl_SetIndices,
3865 IDirect3DDevice8Impl_GetIndices,
3866 IDirect3DDevice8Impl_CreatePixelShader,
3867 IDirect3DDevice8Impl_SetPixelShader,
3868 IDirect3DDevice8Impl_GetPixelShader,
3869 IDirect3DDevice8Impl_DeletePixelShader,
3870 IDirect3DDevice8Impl_SetPixelShaderConstant,
3871 IDirect3DDevice8Impl_GetPixelShaderConstant,
3872 IDirect3DDevice8Impl_GetPixelShaderFunction,
3873 IDirect3DDevice8Impl_DrawRectPatch,
3874 IDirect3DDevice8Impl_DrawTriPatch,
3875 IDirect3DDevice8Impl_DeletePatch
3878 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface) {
3879 ICOM_THIS(IDirect3DDevice8Impl,iface);
3880 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
3881 #if 0
3882 if (This->glCtx != This->render_ctx) {
3883 glXDestroyContext(This->display, This->render_ctx);
3884 This->render_ctx = This->glCtx;
3886 #endif
3887 if (This->win != This->drawable) {
3888 glXDestroyPbuffer(This->display, This->drawable);
3889 This->drawable = This->win;
3891 #endif
3892 return D3D_OK;
3895 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
3896 IDirect3DSurface8* RenderSurface,
3897 IDirect3DSurface8* StencilSurface) {
3900 * Currently only active for GLX >= 1.3
3901 * for others versions we'll have to use GLXPixmaps
3903 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
3904 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
3905 * so only check OpenGL version
3907 #if defined(GL_VERSION_1_3)
3909 GLXFBConfig* cfgs = NULL;
3910 int nCfgs = 0;
3911 int attribs[256];
3912 int nAttribs = 0;
3913 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
3914 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
3915 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
3916 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
3917 IDirect3DSurface8Impl* tmp;
3919 ICOM_THIS(IDirect3DDevice8Impl,iface);
3921 #define PUSH1(att) attribs[nAttribs++] = (att);
3922 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
3924 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
3925 PUSH2(GLX_X_RENDERABLE, TRUE);
3926 PUSH2(GLX_DOUBLEBUFFER, TRUE);
3928 switch (BackBufferFormat) {
3929 /* color buffer */
3930 case D3DFMT_P8:
3931 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
3932 PUSH2(GLX_BUFFER_SIZE, 8);
3933 PUSH2(GLX_DOUBLEBUFFER, TRUE);
3934 break;
3936 case D3DFMT_R3G3B2:
3937 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
3938 PUSH2(GLX_RED_SIZE, 3);
3939 PUSH2(GLX_GREEN_SIZE, 3);
3940 PUSH2(GLX_BLUE_SIZE, 2);
3941 break;
3943 case D3DFMT_A1R5G5B5:
3944 PUSH2(GLX_ALPHA_SIZE, 1);
3945 case D3DFMT_X1R5G5B5:
3946 PUSH2(GLX_RED_SIZE, 5);
3947 PUSH2(GLX_GREEN_SIZE, 5);
3948 PUSH2(GLX_BLUE_SIZE, 5);
3949 break;
3951 case D3DFMT_R5G6B5:
3952 PUSH2(GLX_RED_SIZE, 5);
3953 PUSH2(GLX_GREEN_SIZE, 6);
3954 PUSH2(GLX_BLUE_SIZE, 5);
3955 break;
3957 case D3DFMT_A4R4G4B4:
3958 PUSH2(GLX_ALPHA_SIZE, 4);
3959 case D3DFMT_X4R4G4B4:
3960 PUSH2(GLX_RED_SIZE, 4);
3961 PUSH2(GLX_GREEN_SIZE, 4);
3962 PUSH2(GLX_BLUE_SIZE, 4);
3963 break;
3965 case D3DFMT_A8R8G8B8:
3966 PUSH2(GLX_ALPHA_SIZE, 8);
3967 case D3DFMT_R8G8B8:
3968 case D3DFMT_X8R8G8B8:
3969 PUSH2(GLX_RED_SIZE, 8);
3970 PUSH2(GLX_GREEN_SIZE, 8);
3971 PUSH2(GLX_BLUE_SIZE, 8);
3972 break;
3974 default:
3975 break;
3978 switch (StencilBufferFormat) {
3979 case D3DFMT_D16_LOCKABLE:
3980 case D3DFMT_D16:
3981 PUSH2(GLX_DEPTH_SIZE, 16);
3982 break;
3984 case D3DFMT_D15S1:
3985 PUSH2(GLX_DEPTH_SIZE, 15);
3986 break;
3988 case D3DFMT_D24X8:
3989 PUSH2(GLX_DEPTH_SIZE, 24);
3990 break;
3992 case D3DFMT_D24X4S4:
3993 PUSH2(GLX_DEPTH_SIZE, 24);
3994 PUSH2(GLX_STENCIL_SIZE, 4);
3995 break;
3997 case D3DFMT_D24S8:
3998 PUSH2(GLX_DEPTH_SIZE, 24);
3999 PUSH2(GLX_STENCIL_SIZE, 8);
4000 break;
4002 case D3DFMT_D32:
4003 PUSH2(GLX_DEPTH_SIZE, 32);
4004 break;
4006 default:
4007 break;
4010 PUSH1(None);
4012 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4013 if (NULL != cfgs) {
4014 #if 0
4015 int i;
4016 for (i = 0; i < nCfgs; ++i) {
4017 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4019 #endif
4021 if (NULL != This->renderTarget) {
4022 GLenum prev_read;
4023 glFlush();
4024 vcheckGLcall("glFlush");
4026 #if 0
4027 /** very very usefull debug code */
4028 glXSwapBuffers(This->display, This->drawable);
4029 printf("Hit Enter to get next frame ...\n");
4030 getchar();
4031 #endif
4033 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4034 vcheckGLcall("glIntegerv");
4035 glReadBuffer(GL_BACK);
4036 vcheckGLcall("glReadBuffer");
4038 long j;
4039 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4040 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4041 glReadPixels(0,
4042 This->renderTarget->myDesc.Height - j - 1,
4043 This->renderTarget->myDesc.Width,
4045 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4046 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4047 This->renderTarget->allocatedMemory + j * pitch);
4048 vcheckGLcall("glReadPixels");
4051 glReadBuffer(prev_read);
4052 vcheckGLcall("glReadBuffer");
4055 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4056 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4057 nAttribs = 0;
4058 PUSH2(GLX_PBUFFER_WIDTH, Width);
4059 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4060 PUSH1(None);
4061 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4063 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4064 if (NULL == This->render_ctx) {
4065 ERR("cannot create glxContext\n");
4068 glFlush();
4069 glXSwapBuffers(This->display, This->drawable);
4070 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4071 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4073 checkGLcall("glXMakeContextCurrent");
4076 tmp = This->renderTarget;
4077 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4078 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4079 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4081 tmp = This->stencilBufferTarget;
4082 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4083 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4084 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4086 return D3D_OK;
4088 } else {
4089 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4092 #undef PUSH1
4093 #undef PUSH2
4095 #endif
4097 return D3DERR_INVALIDCALL;