Fixed header dependencies to be fully compatible with the Windows
[wine/multimedia.git] / dlls / d3d8 / device.c
blob47d2fa0e9565b4b08830db5adad18d1194547517
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>
24 #include <stdarg.h>
26 #define NONAMELESSUNION
27 #define NONAMELESSSTRUCT
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winuser.h"
31 #include "wingdi.h"
32 #include "wine/debug.h"
34 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
35 /*#define GL_GLEXT_PROTOTYPES*/
36 /*#undef GLX_GLXEXT_LEGACY*/
37 #include "d3d8_private.h"
39 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
40 #undef GL_VERSION_1_4
42 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
43 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
44 WINE_DECLARE_DEBUG_CHANNEL(fps);
46 IDirect3DVertexShaderImpl* VertexShaders[64];
47 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
48 IDirect3DPixelShaderImpl* PixelShaders[64];
50 /* Debugging aids: */
51 #ifdef FRAME_DEBUGGING
52 BOOL isOn = FALSE;
53 BOOL isDumpingFrames = FALSE;
54 LONG primCounter = 0;
55 #endif
58 * Utility functions or macros
60 #define conv_mat(mat,gl_mat) \
61 do { \
62 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
63 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
64 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
65 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
66 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
67 } while (0)
69 /* Apply the current values to the specified texture stage */
70 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage, DWORD Flags) {
71 ICOM_THIS(IDirect3DDevice8Impl,iface);
72 int i = 0;
73 float col[4];
74 BOOL changeTexture = TRUE;
76 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
77 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
79 BOOL skip = FALSE;
81 switch (i) {
82 /* Performance: For texture states where multiples effect the outcome, only bother
83 applying the last one as it will pick up all the other values */
84 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
85 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
86 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
87 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
88 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
89 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
90 skip = TRUE;
91 break;
93 /* Performance: If the texture states only impact settings for the texture unit
94 (compared to the texture object) then there is no need to reapply them. The
95 only time they need applying is the first time, since we cheat and put the
96 values into the stateblock without applying.
97 Per-texture unit: texture function (eg. combine), ops and args
98 texture env color
99 texture generation settings
100 Note: Due to some special conditions there may be a need to do particular ones
101 of these, which is what the Flags allows */
102 case D3DTSS_COLOROP:
103 case D3DTSS_TEXCOORDINDEX:
104 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
105 break;
107 case D3DTSS_ALPHAOP:
108 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
109 break;
111 default:
112 skip = FALSE;
115 if (skip == FALSE) {
116 /* Performance: Only change to this texture if we have to */
117 if (changeTexture) {
118 /* Make appropriate texture active */
119 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
120 #if defined(GL_VERSION_1_3)
121 glActiveTexture(GL_TEXTURE0 + Stage);
122 #else
123 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
124 #endif
125 checkGLcall("glActiveTextureARB");
126 } else if (Stage > 0) {
127 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
129 changeTexture = FALSE;
132 /* Now apply the change */
133 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
137 /* Note the D3DRS value applies to all textures, but GL has one
138 * per texture, so apply it now ready to be used!
140 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
141 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
142 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
144 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
147 /* Setup this textures matrix */
148 static void set_texture_matrix(float *smat, DWORD flags)
150 float mat[16];
152 glMatrixMode(GL_TEXTURE);
154 if (flags == D3DTTFF_DISABLE) {
155 glLoadIdentity();
156 checkGLcall("glLoadIdentity()");
157 return;
160 if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
161 ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
162 checkGLcall("glLoadIdentity()");
163 return;
166 memcpy(mat, smat, 16*sizeof(float));
168 switch (flags & ~D3DTTFF_PROJECTED) {
169 case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
170 case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
171 default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
174 if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
175 case D3DTTFF_COUNT2:
176 mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
177 mat[1] = mat[5] = mat[9] = mat[13] = 0;
178 break;
179 case D3DTTFF_COUNT3:
180 mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
181 mat[2] = mat[6] = mat[10] = mat[14] = 0;
182 break;
184 glLoadMatrixf(mat);
185 checkGLcall("glLoadMatrixf(mat)");
188 /* IDirect3D IUnknown parts follow: */
189 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
191 ICOM_THIS(IDirect3DDevice8Impl,iface);
193 if (IsEqualGUID(riid, &IID_IUnknown)
194 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
195 IDirect3DDevice8Impl_AddRef(iface);
196 *ppobj = This;
197 return D3D_OK;
200 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
201 return E_NOINTERFACE;
204 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
205 ICOM_THIS(IDirect3DDevice8Impl,iface);
206 TRACE("(%p) : AddRef from %ld\n", This, This->ref);
207 return ++(This->ref);
210 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
211 ICOM_THIS(IDirect3DDevice8Impl,iface);
212 ULONG ref = --This->ref;
213 TRACE("(%p) : ReleaseRef to %ld\n", This, This->ref);
214 if (ref == 0) {
215 IDirect3DDevice8Impl_CleanRender(iface);
216 HeapFree(GetProcessHeap(), 0, This);
218 return ref;
221 /* IDirect3DDevice Interface follow: */
222 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
223 ICOM_THIS(IDirect3DDevice8Impl,iface);
224 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
225 return D3D_OK;
228 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
229 ICOM_THIS(IDirect3DDevice8Impl,iface);
230 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
232 * pretend we have 32MB of any type of memory queried.
234 return (1024*1024*32);
237 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
238 ICOM_THIS(IDirect3DDevice8Impl,iface);
239 FIXME("(%p) : stub\n", This); return D3D_OK;
241 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
242 ICOM_THIS(IDirect3DDevice8Impl,iface);
243 TRACE("(%p) : returning %p\n", This, This->direct3d8);
245 /* Inc ref count */
246 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
248 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
249 return D3D_OK;
251 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
252 ICOM_THIS(IDirect3DDevice8Impl,iface);
253 FIXME("(%p) : stub, calling idirect3d for now\n", This);
254 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
255 return D3D_OK;
257 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
259 HDC hdc;
260 int bpp = 0;
262 ICOM_THIS(IDirect3DDevice8Impl,iface);
263 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
264 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
265 pMode->RefreshRate = 85; /*FIXME: How to identify? */
267 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
268 bpp = GetDeviceCaps(hdc, BITSPIXEL);
269 DeleteDC(hdc);
271 switch (bpp) {
272 case 8: pMode->Format = D3DFMT_R8G8B8; break;
273 case 16: pMode->Format = D3DFMT_R5G6B5; break;
274 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
275 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
276 default:
277 FIXME("Unrecognized display mode format\n");
278 pMode->Format = D3DFMT_UNKNOWN;
281 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
282 pMode->Format, debug_d3dformat(pMode->Format));
283 return D3D_OK;
285 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
286 ICOM_THIS(IDirect3DDevice8Impl,iface);
287 TRACE("(%p) copying to %p\n", This, pParameters);
288 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
289 return D3D_OK;
291 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
292 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
293 ICOM_THIS(IDirect3DDevice8Impl,iface);
294 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
296 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
297 ERR("(%p) : surface(%p) have a invalid format\n", This, pCursorBitmap);
298 return D3DERR_INVALIDCALL;
300 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
301 ERR("(%p) : surface(%p) have a invalid size\n", This, pCursorBitmap);
302 return D3DERR_INVALIDCALL;
305 This->xHotSpot = XHotSpot;
306 This->yHotSpot = YHotSpot;
307 return D3D_OK;
309 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
310 ICOM_THIS(IDirect3DDevice8Impl,iface);
311 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
312 This->xScreenSpace = XScreenSpace;
313 This->yScreenSpace = YScreenSpace;
314 return;
316 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
317 ICOM_THIS(IDirect3DDevice8Impl,iface);
318 TRACE("(%p) : visible(%d)\n", This, bShow);
319 This->bCursorVisible = bShow;
320 return D3D_OK;
322 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
323 IDirect3DSwapChain8Impl* object;
324 ICOM_THIS(IDirect3DDevice8Impl,iface);
325 FIXME("(%p) : stub\n", This);
327 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
328 if (NULL == object) {
329 return D3DERR_OUTOFVIDEOMEMORY;
331 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
332 object->ref = 1;
334 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
335 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
336 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
338 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
339 (pPresentationParameters->BackBufferHeight == 0))) {
340 RECT Rect;
342 GetClientRect(This->win_handle, &Rect);
344 if (pPresentationParameters->BackBufferWidth == 0) {
345 pPresentationParameters->BackBufferWidth = Rect.right;
346 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
348 if (pPresentationParameters->BackBufferHeight == 0) {
349 pPresentationParameters->BackBufferHeight = Rect.bottom;
350 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
354 /* Save the presentation parms now filled in correctly */
355 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
357 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
358 pPresentationParameters->BackBufferWidth,
359 pPresentationParameters->BackBufferHeight,
360 pPresentationParameters->BackBufferFormat,
361 pPresentationParameters->MultiSampleType,
362 TRUE,
363 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
365 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
366 pPresentationParameters->BackBufferWidth,
367 pPresentationParameters->BackBufferHeight,
368 pPresentationParameters->BackBufferFormat,
369 pPresentationParameters->MultiSampleType,
370 TRUE,
371 (LPDIRECT3DSURFACE8*) &object->backBuffer);
373 if (pPresentationParameters->EnableAutoDepthStencil) {
374 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
375 pPresentationParameters->BackBufferWidth,
376 pPresentationParameters->BackBufferHeight,
377 pPresentationParameters->AutoDepthStencilFormat,
378 D3DMULTISAMPLE_NONE,
379 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
380 } else {
381 object->depthStencilBuffer = NULL;
384 *pSwapChain = (IDirect3DSwapChain8*) object;
385 return D3D_OK;
387 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
388 ICOM_THIS(IDirect3DDevice8Impl,iface);
389 FIXME("(%p) : stub\n", This); return D3D_OK;
391 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface, CONST RECT* pSourceRect,CONST RECT* pDestRect,HWND hDestWindowOverride,CONST RGNDATA* pDirtyRegion) {
392 ICOM_THIS(IDirect3DDevice8Impl,iface);
393 TRACE("(%p) : complete stub!\n", This);
395 ENTER_GL();
397 glXSwapBuffers(This->display, This->drawable);
398 /* Dont call checkGLcall, as glGetError is not applicable here */
399 TRACE("glXSwapBuffers called, Starting new frame\n");
401 /* FPS support */
402 if (TRACE_ON(fps))
404 static long prev_time, frames;
406 DWORD time = GetTickCount();
407 frames++;
408 /* every 1.5 seconds */
409 if (time - prev_time > 1500) {
410 TRACE_(fps)("@@@ %.2ffps\n", 1000.0*frames/(time - prev_time));
411 prev_time = time;
412 frames = 0;
416 #if defined(FRAME_DEBUGGING)
418 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
419 if (!isOn) {
420 isOn = TRUE;
421 FIXME("Enabling D3D Trace\n");
422 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
423 #if defined(SHOW_FRAME_MAKEUP)
424 FIXME("Singe Frame snapshots Starting\n");
425 isDumpingFrames = TRUE;
426 glClear(GL_COLOR_BUFFER_BIT);
427 #endif
429 #if defined(SINGLE_FRAME_DEBUGGING)
430 } else {
431 #if defined(SHOW_FRAME_MAKEUP)
432 FIXME("Singe Frame snapshots Finishing\n");
433 isDumpingFrames = FALSE;
434 #endif
435 FIXME("Singe Frame trace complete\n");
436 DeleteFileA("C:\\D3DTRACE");
437 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
438 #endif
440 } else {
441 if (isOn) {
442 isOn = FALSE;
443 #if defined(SHOW_FRAME_MAKEUP)
444 FIXME("Singe Frame snapshots Finishing\n");
445 isDumpingFrames = FALSE;
446 #endif
447 FIXME("Disabling D3D Trace\n");
448 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
452 #endif
454 LEAVE_GL();
456 return D3D_OK;
458 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
459 ICOM_THIS(IDirect3DDevice8Impl,iface);
460 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
461 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
463 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
464 FIXME("Only one backBuffer currently supported\n");
465 return D3DERR_INVALIDCALL;
468 /* Note inc ref on returned surface */
469 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
471 return D3D_OK;
473 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
474 ICOM_THIS(IDirect3DDevice8Impl,iface);
475 FIXME("(%p) : stub\n", This);
476 return D3D_OK;
478 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
479 HDC hDC;
480 ICOM_THIS(IDirect3DDevice8Impl,iface);
482 FIXME("(%p) : pRamp@%p\n", This, pRamp);
483 hDC = GetDC(This->win_handle);
484 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
485 ReleaseDC(This->win_handle, hDC);
486 return;
488 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
489 HDC hDC;
490 ICOM_THIS(IDirect3DDevice8Impl,iface);
492 FIXME("(%p) : pRamp@%p\n", This, pRamp);
493 hDC = GetDC(This->win_handle);
494 GetDeviceGammaRamp(hDC, pRamp);
495 ReleaseDC(This->win_handle, hDC);
496 return;
498 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
499 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
500 IDirect3DTexture8Impl *object;
501 int i;
502 UINT tmpW;
503 UINT tmpH;
505 ICOM_THIS(IDirect3DDevice8Impl,iface);
507 /* Allocate the storage for the device */
508 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);
509 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
510 object->lpVtbl = &Direct3DTexture8_Vtbl;
511 object->Device = This;
512 object->ResourceType = D3DRTYPE_TEXTURE;
513 object->ref = 1;
514 object->width = Width;
515 object->height = Height;
516 object->levels = Levels;
517 object->usage = Usage;
518 object->format = Format;
520 /* Calculate levels for mip mapping */
521 if (Levels == 0) {
522 object->levels++;
523 tmpW = Width;
524 tmpH = Height;
525 while (tmpW > 1 && tmpH > 1) {
526 tmpW = max(1, tmpW / 2);
527 tmpH = max(1, tmpH / 2);
528 object->levels++;
530 TRACE("Calculated levels = %d\n", object->levels);
533 /* Generate all the surfaces */
534 tmpW = Width;
535 tmpH = Height;
536 for (i = 0; i < object->levels; i++)
538 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
539 object->surfaces[i]->Container = (IUnknown*) object;
540 object->surfaces[i]->myDesc.Usage = Usage;
541 object->surfaces[i]->myDesc.Pool = Pool;
542 /**
543 * As written in msdn in IDirect3DTexture8::LockRect
544 * Textures created in D3DPOOL_DEFAULT are not lockable.
546 if (D3DPOOL_DEFAULT == Pool) {
547 object->surfaces[i]->lockable = FALSE;
550 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
551 tmpW = max(1, tmpW / 2);
552 tmpH = max(1, tmpH / 2);
555 *ppTexture = (LPDIRECT3DTEXTURE8) object;
556 TRACE("(%p) : Created texture %p\n", This, object);
557 return D3D_OK;
559 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
560 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
561 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
563 IDirect3DVolumeTexture8Impl *object;
564 int i;
565 UINT tmpW;
566 UINT tmpH;
567 UINT tmpD;
569 ICOM_THIS(IDirect3DDevice8Impl,iface);
571 /* Allocate the storage for it */
572 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));
573 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
574 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
575 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
576 object->Device = This;
577 object->ref = 1;
579 object->width = Width;
580 object->height = Height;
581 object->depth = Depth;
582 object->levels = Levels;
583 object->usage = Usage;
584 object->format = Format;
586 /* Calculate levels for mip mapping */
587 if (Levels == 0) {
588 object->levels++;
589 tmpW = Width;
590 tmpH = Height;
591 tmpD = Depth;
592 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
593 tmpW = max(1, tmpW / 2);
594 tmpH = max(1, tmpH / 2);
595 tmpD = max(1, tmpD / 2);
596 object->levels++;
598 TRACE("Calculated levels = %d\n", object->levels);
601 /* Generate all the surfaces */
602 tmpW = Width;
603 tmpH = Height;
604 tmpD = Depth;
606 for (i = 0; i < object->levels; i++)
608 IDirect3DVolume8Impl* volume;
610 /* Create the volume - No entry point for this seperately?? */
611 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
612 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
614 volume->lpVtbl = &Direct3DVolume8_Vtbl;
615 volume->Device = This;
616 volume->ResourceType = D3DRTYPE_VOLUME;
617 volume->Container = (IUnknown*) object;
618 volume->ref = 1;
620 volume->myDesc.Width = Width;
621 volume->myDesc.Height = Height;
622 volume->myDesc.Depth = Depth;
623 volume->myDesc.Format = Format;
624 volume->myDesc.Type = D3DRTYPE_VOLUME;
625 volume->myDesc.Pool = Pool;
626 volume->myDesc.Usage = Usage;
627 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
628 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
629 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
631 volume->lockable = TRUE;
632 volume->locked = FALSE;
633 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
634 volume->Dirty = FALSE;
635 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
637 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
638 This, Width, Height, Depth, Format, debug_d3dformat(Format),
639 volume, volume->allocatedMemory, volume->myDesc.Size);
641 tmpW = max(1, tmpW / 2);
642 tmpH = max(1, tmpH / 2);
643 tmpD = max(1, tmpD / 2);
646 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
647 TRACE("(%p) : Created volume texture %p\n", This, object);
648 return D3D_OK;
650 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
651 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
653 IDirect3DCubeTexture8Impl *object;
654 ICOM_THIS(IDirect3DDevice8Impl,iface);
655 int i,j;
656 UINT tmpW;
658 /* Allocate the storage for it */
659 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));
660 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
661 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
662 object->ref = 1;
663 object->Device = This;
664 object->ResourceType = D3DRTYPE_CUBETEXTURE;
666 object->edgeLength = EdgeLength;
667 object->levels = Levels;
668 object->usage = Usage;
669 object->format = Format;
671 /* Calculate levels for mip mapping */
672 if (Levels == 0) {
673 object->levels++;
674 tmpW = EdgeLength;
675 while (tmpW > 1) {
676 tmpW = max(1, tmpW / 2);
677 object->levels++;
679 TRACE("Calculated levels = %d\n", object->levels);
682 /* Generate all the surfaces */
683 tmpW = EdgeLength;
684 for (i = 0; i < object->levels; i++) {
685 /* Create the 6 faces */
686 for (j = 0; j < 6; j++) {
687 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
688 object->surfaces[j][i]->Container = (IUnknown*) object;
689 object->surfaces[j][i]->myDesc.Usage = Usage;
690 object->surfaces[j][i]->myDesc.Pool = Pool;
691 /**
692 * As written in msdn in IDirect3DCubeTexture8::LockRect
693 * Textures created in D3DPOOL_DEFAULT are not lockable.
695 if (D3DPOOL_DEFAULT == Pool) {
696 object->surfaces[j][i]->lockable = FALSE;
699 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
701 tmpW = max(1, tmpW / 2);
704 TRACE("(%p) : Iface@%p\n", This, object);
705 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
706 return D3D_OK;
708 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
709 IDirect3DVertexBuffer8Impl *object;
711 ICOM_THIS(IDirect3DDevice8Impl,iface);
713 /* Allocate the storage for the device */
714 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
715 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
716 object->Device = This;
717 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
718 object->ref = 1;
719 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
720 object->currentDesc.Usage = Usage;
721 object->currentDesc.Pool = Pool;
722 object->currentDesc.FVF = FVF;
723 object->currentDesc.Size = Size;
725 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
727 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
729 return D3D_OK;
731 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
732 IDirect3DIndexBuffer8Impl *object;
734 ICOM_THIS(IDirect3DDevice8Impl,iface);
735 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
737 /* Allocate the storage for the device */
738 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
739 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
740 object->Device = This;
741 object->ref = 1;
742 object->ResourceType = D3DRTYPE_INDEXBUFFER;
744 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
745 object->currentDesc.Usage = Usage;
746 object->currentDesc.Pool = Pool;
747 object->currentDesc.Format = Format;
748 object->currentDesc.Size = Length;
750 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
752 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
754 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
756 return D3D_OK;
758 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
759 IDirect3DSurface8Impl *object;
760 ICOM_THIS(IDirect3DDevice8Impl,iface);
762 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
763 if (NULL == object) {
764 *ppSurface = NULL;
765 return D3DERR_OUTOFVIDEOMEMORY;
767 *ppSurface = (LPDIRECT3DSURFACE8) object;
768 object->lpVtbl = &Direct3DSurface8_Vtbl;
769 object->Device = This;
770 object->ResourceType = D3DRTYPE_SURFACE;
771 object->Container = (IUnknown*) This;
773 object->ref = 1;
774 object->myDesc.Width = Width;
775 object->myDesc.Height = Height;
776 object->myDesc.Format = Format;
777 object->myDesc.Type = D3DRTYPE_SURFACE;
778 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
779 object->myDesc.Pool = D3DPOOL_DEFAULT;
780 object->myDesc.MultiSampleType = MultiSample;
781 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
782 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
783 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
784 object->lockable = Lockable;
785 object->locked = FALSE;
786 memset(&object->lockedRect, 0, sizeof(RECT));
787 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
789 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);
790 return D3D_OK;
792 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
793 IDirect3DSurface8Impl *object;
795 ICOM_THIS(IDirect3DDevice8Impl,iface);
797 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
798 if (NULL == object) {
799 *ppSurface = NULL;
800 return D3DERR_OUTOFVIDEOMEMORY;
802 *ppSurface = (LPDIRECT3DSURFACE8) object;
803 object->lpVtbl = &Direct3DSurface8_Vtbl;
804 object->Device = This;
805 object->ResourceType = D3DRTYPE_SURFACE;
806 object->Container = (IUnknown*) This;
808 object->ref = 1;
809 object->myDesc.Width = Width;
810 object->myDesc.Height = Height;
811 object->myDesc.Format = Format;
812 object->myDesc.Type = D3DRTYPE_SURFACE;
813 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
814 object->myDesc.Pool = D3DPOOL_DEFAULT;
815 object->myDesc.MultiSampleType = MultiSample;
816 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
817 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
818 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
819 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
820 object->locked = FALSE;
821 memset(&object->lockedRect, 0, sizeof(RECT));
822 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
824 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);
825 return D3D_OK;
827 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
828 IDirect3DSurface8Impl *object;
830 ICOM_THIS(IDirect3DDevice8Impl,iface);
832 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
833 *ppSurface = (LPDIRECT3DSURFACE8) object;
834 object->lpVtbl = &Direct3DSurface8_Vtbl;
835 object->Device = This;
836 object->ResourceType = D3DRTYPE_SURFACE;
837 object->Container = (IUnknown*) This;
839 object->ref = 1;
840 object->myDesc.Width = Width;
841 object->myDesc.Height = Height;
842 object->myDesc.Format = Format;
843 object->myDesc.Type = D3DRTYPE_SURFACE;
844 object->myDesc.Usage = 0;
845 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
846 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
847 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
848 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
849 object->lockable = TRUE;
850 object->locked = FALSE;
851 memset(&object->lockedRect, 0, sizeof(RECT));
852 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
854 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);
855 return D3D_OK;
857 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
858 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
859 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
861 HRESULT rc = D3D_OK;
862 IDirect3DBaseTexture8* texture = NULL;
865 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
866 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
868 ICOM_THIS(IDirect3DDevice8Impl,iface);
869 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
870 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
872 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
873 a sample and doesnt seem to break anything as far as I can tell */
874 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
875 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
876 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
877 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
878 rc = D3DERR_INVALIDCALL;
880 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
881 TRACE("Converting dest to same format as source, since dest was unknown\n");
882 dst->myDesc.Format = src->myDesc.Format;
884 /* Convert container as well */
885 IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
886 if (texture != NULL) {
887 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
888 /** Releasing texture after GetContainer */
889 IDirect3DBaseTexture8_Release(texture);
890 texture = NULL;
894 /* Quick if complete copy ... */
895 if (rc == D3D_OK && cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
897 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
899 D3DLOCKED_RECT lrSrc;
900 D3DLOCKED_RECT lrDst;
901 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
902 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
903 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
905 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
907 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
908 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
909 TRACE("Unlocked src and dst\n");
911 } else {
913 FIXME("Wanted to copy all surfaces but size not compatible\n");
914 rc = D3DERR_INVALIDCALL;
918 } else {
920 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
922 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
923 int i;
924 /* Copy rect by rect */
925 for (i = 0; i < cRects; i++) {
926 CONST RECT* r = &pSourceRectsArray[i];
927 CONST POINT* p = &pDestPointsArray[i];
928 int copyperline = (r->right - r->left) * bytesPerPixel;
929 int j;
930 D3DLOCKED_RECT lrSrc;
931 D3DLOCKED_RECT lrDst;
932 RECT dest_rect;
935 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
937 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
938 dest_rect.left = p->x;
939 dest_rect.top = p->y;
940 dest_rect.right = p->x + (r->right - r->left);
941 dest_rect.left = p->y + (r->bottom - r->top);
942 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
943 TRACE("Locked src and dst\n");
945 /* Find where to start */
946 #if 0
947 from = copyfrom + (r->top * pitchFrom) + (r->left * bytesPerPixel);
948 to = copyto + (p->y * pitchTo) + (p->x * bytesPerPixel);
949 /* Copy line by line */
950 for (j = 0; j < (r->bottom - r->top); j++) {
951 memcpy(to + (j * pitchTo), from + (j * pitchFrom), copyperline);
953 #endif
955 for (j = 0; j < (r->bottom - r->top); j++) {
956 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
959 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
960 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
961 TRACE("Unlocked src and dst\n");
964 } else {
966 FIXME("Wanted to copy partial surfaces not implemented\n");
967 rc = D3DERR_INVALIDCALL;
972 return rc;
974 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
975 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
976 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
977 D3DRESOURCETYPE srcType;
978 D3DRESOURCETYPE dstType;
980 ICOM_THIS(IDirect3DDevice8Impl,iface);
981 TRACE("(%p) : first try\n", This);
983 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
984 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
986 if (srcType != dstType) {
987 return D3DERR_INVALIDCALL;
989 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
990 return D3DERR_INVALIDCALL;
992 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
993 return D3DERR_INVALIDCALL;
995 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
996 /** Only copy Dirty textures */
997 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
998 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
999 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1000 UINT i, j;
1002 for (i = skipLevels; i < srcLevelCnt; ++i) {
1003 HRESULT hr;
1005 switch (srcType) {
1006 case D3DRTYPE_TEXTURE:
1008 IDirect3DSurface8* srcSur = NULL;
1009 IDirect3DSurface8* dstSur = NULL;
1010 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1011 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1013 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1014 about dst with less levels than the source?) */
1015 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1017 IDirect3DSurface8Impl_Release(srcSur);
1018 IDirect3DSurface8Impl_Release(dstSur);
1020 break;
1021 case D3DRTYPE_VOLUMETEXTURE:
1023 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1025 break;
1026 case D3DRTYPE_CUBETEXTURE:
1028 IDirect3DSurface8* srcSur = NULL;
1029 IDirect3DSurface8* dstSur = NULL;
1030 for (j = 0; j < 5; ++j) {
1031 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1032 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1033 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1034 IDirect3DSurface8Impl_Release(srcSur);
1035 IDirect3DSurface8Impl_Release(dstSur);
1038 break;
1039 default:
1040 break;
1043 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1046 return D3D_OK;
1048 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1049 HRESULT hr;
1050 D3DLOCKED_RECT lockedRect;
1051 RECT wantedRect;
1052 GLint prev_store;
1053 GLenum prev_read;
1055 ICOM_THIS(IDirect3DDevice8Impl,iface);
1057 FIXME("(%p) : see if behavior correct\n", This);
1059 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1060 ERR("(%p) : surface(%p) have a invalid format\n", This, pDestSurface);
1061 return D3DERR_INVALIDCALL;
1064 wantedRect.left = 0;
1065 wantedRect.top = 0;
1066 wantedRect.right = This->PresentParms.BackBufferWidth;
1067 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1069 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1070 if (FAILED(hr)) {
1071 ERR("(%p) : cannot lock surface\n", This);
1072 return D3DERR_INVALIDCALL;
1075 ENTER_GL();
1079 IDirect3DSurface8Impl* tmp = ((IDirect3DSurface8Impl*) pDestSurface);
1080 FIXME("dest:%u,%u,bpp:%u\n", tmp->myDesc.Width, tmp->myDesc.Height, tmp->bytesPerPixel);
1081 FIXME("dest2:pitch%u\n", lockedRect.Pitch);
1082 FIXME("src:%u,%u\n", This->PresentParms.BackBufferWidth, This->PresentParms.BackBufferHeight);
1083 tmp = This->frontBuffer;
1084 FIXME("src2:%u,%u,bpp:%u\n", tmp->myDesc.Width, tmp->myDesc.Height, tmp->bytesPerPixel);
1088 glFlush();
1089 vcheckGLcall("glFlush");
1090 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1091 vcheckGLcall("glIntegerv");
1092 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1093 vcheckGLcall("glIntegerv");
1095 glReadBuffer(GL_FRONT);
1096 vcheckGLcall("glReadBuffer");
1097 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1098 vcheckGLcall("glPixelStorei");
1099 /* stupid copy */
1101 long j;
1102 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1103 /*memcpy(lockedRect.pBits + (j * lockedRect.Pitch), This->frontBuffer->allocatedMemory + (j * i), i);*/
1104 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1105 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1106 vcheckGLcall("glReadPixels");
1109 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1110 vcheckGLcall("glPixelStorei");
1111 glReadBuffer(prev_read);
1112 vcheckGLcall("glReadBuffer");
1114 LEAVE_GL();
1116 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1117 return hr;
1119 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1120 HRESULT hr;
1122 ICOM_THIS(IDirect3DDevice8Impl,iface);
1124 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1125 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1126 return D3D_OK;
1129 IDirect3DDevice8Impl_CleanRender(iface);
1131 if ((IDirect3DSurface8Impl*) pRenderTarget == This->frontBuffer && (IDirect3DSurface8Impl*) pNewZStencil == This->depthStencilBuffer) {
1132 IDirect3DSurface8Impl* tmp;
1134 TRACE("retoring SetRenderTarget defaults\n");
1136 tmp = This->renderTarget;
1137 This->renderTarget = (IDirect3DSurface8Impl*) This->frontBuffer;
1138 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
1139 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1141 tmp = This->stencilBufferTarget;
1142 This->stencilBufferTarget = (IDirect3DSurface8Impl*) This->depthStencilBuffer;
1143 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
1144 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
1146 return D3D_OK;
1149 TRACE("(%p) : expect crash newRender@%p newZStencil@%p\n", This, pRenderTarget, pNewZStencil);
1151 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1153 return hr;
1156 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1157 ICOM_THIS(IDirect3DDevice8Impl,iface);
1159 TRACE("(%p)->(%p) default(%p)\n", This, This->renderTarget, This->frontBuffer);
1161 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1162 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1164 return D3D_OK;
1167 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1168 ICOM_THIS(IDirect3DDevice8Impl,iface);
1170 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1172 /* Note inc ref on returned surface */
1173 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1174 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1176 return D3D_OK;
1179 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1180 ICOM_THIS(IDirect3DDevice8Impl,iface);
1181 TRACE("(%p) : stub\n", This);
1182 return D3D_OK;
1184 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1185 IDirect3DBaseTexture8* cont = NULL;
1186 HRESULT hr;
1187 ICOM_THIS(IDirect3DDevice8Impl,iface);
1188 TRACE("(%p)\n", This);
1190 ENTER_GL();
1192 glFlush();
1193 checkGLcall("glFlush");
1195 /* Useful for debugging sometimes!
1196 printf("Hit Enter ...\n");
1197 getchar(); */
1199 if (This->frontBuffer != This->renderTarget) {
1201 GLenum prev_read;
1202 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1203 vcheckGLcall("glIntegerv");
1204 glReadBuffer(GL_BACK);
1205 vcheckGLcall("glReadBuffer");
1207 long j;
1208 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1209 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1210 glReadPixels(0,
1211 This->renderTarget->myDesc.Height - j - 1,
1212 This->renderTarget->myDesc.Width,
1214 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1215 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1216 This->renderTarget->allocatedMemory + j * pitch);
1217 vcheckGLcall("glReadPixels");
1220 glReadBuffer(prev_read);
1221 vcheckGLcall("glReadBuffer");
1224 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1225 if (SUCCEEDED(hr) && NULL != cont) {
1226 /** always dirtify for now. we must find a better way to see that surface have been modified */
1227 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1228 IDirect3DBaseTexture8_PreLoad(cont);
1229 IDirect3DBaseTexture8Impl_Release(cont);
1230 cont = NULL;
1234 LEAVE_GL();
1235 return D3D_OK;
1237 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1238 ICOM_THIS(IDirect3DDevice8Impl,iface);
1240 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1241 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1242 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1243 GLbitfield glMask = 0;
1244 GLboolean old_ztest;
1245 GLfloat old_z_clear_value;
1246 GLint old_stencil_clear_value;
1247 GLfloat old_color_clear_value[4];
1248 int i;
1249 CONST D3DRECT* curRect;
1251 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1252 Count, pRects, Flags, Z, Stencil);
1254 ENTER_GL();
1255 if (Count > 0 && pRects) {
1256 glEnable(GL_SCISSOR_TEST);
1257 checkGLcall("glEnable GL_SCISSOR_TEST");
1258 curRect = pRects;
1259 } else {
1260 curRect = NULL;
1263 /* Only set the values up once, as they are not changing */
1264 if (Flags & D3DCLEAR_STENCIL) {
1265 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1266 glClearStencil(Stencil);
1267 checkGLcall("glClearStencil");
1268 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1271 if (Flags & D3DCLEAR_ZBUFFER) {
1272 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1273 glDepthMask(GL_TRUE);
1274 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1275 glClearDepth(Z);
1276 checkGLcall("glClearDepth");
1277 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1280 if (Flags & D3DCLEAR_TARGET) {
1281 TRACE("Clearing screen with glClear to color %lx\n", Color);
1282 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1283 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1284 ((Color >> 8) & 0xFF) / 255.0f,
1285 ((Color >> 0) & 0xFF) / 255.0f,
1286 ((Color >> 24) & 0xFF) / 255.0f);
1287 checkGLcall("glClearColor");
1288 glMask = glMask | GL_COLOR_BUFFER_BIT;
1291 /* Now process each rect in turn */
1292 for (i = 0; i < Count || i == 0; i++) {
1294 if (curRect) {
1295 /* Note gl uses lower left, width/height */
1296 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1297 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1298 curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1299 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1300 glScissor(curRect->x1, (This->PresentParms.BackBufferHeight - curRect->y2),
1301 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1302 checkGLcall("glScissor");
1305 /* Clear the selected rectangle (or full screen) */
1306 glClear(glMask);
1307 checkGLcall("glClear");
1309 /* Step to the next rectangle */
1310 if (curRect) curRect = curRect + sizeof(D3DRECT);
1313 /* Restore the old values (why..?) */
1314 if (Flags & D3DCLEAR_STENCIL) {
1315 glClearStencil(old_stencil_clear_value);
1317 if (Flags & D3DCLEAR_ZBUFFER) {
1318 glDepthMask(old_ztest);
1319 glClearDepth(old_z_clear_value);
1321 if (Flags & D3DCLEAR_TARGET) {
1322 glClearColor(old_color_clear_value[0],
1323 old_color_clear_value[1],
1324 old_color_clear_value[2],
1325 old_color_clear_value[3]);
1328 if (Count > 0 && pRects) {
1329 glDisable(GL_SCISSOR_TEST);
1330 checkGLcall("glDisable");
1332 LEAVE_GL();
1334 return D3D_OK;
1336 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1337 ICOM_THIS(IDirect3DDevice8Impl,iface);
1338 int k;
1340 /* Most of this routine, comments included copied from ddraw tree initially: */
1341 TRACE("(%p) : State=%d\n", This, d3dts);
1343 /* Handle recording of state blocks */
1344 if (This->isRecordingState) {
1345 TRACE("Recording... not performing anything\n");
1346 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1347 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1348 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1349 return D3D_OK;
1353 * if the new matrix is the same as the current one,
1354 * we cut off any further processing. this seems to be a reasonable
1355 * optimization because as was noticed, some apps (warcraft3 for example)
1356 * tend towards setting the same matrix repeatedly for some dumb reason.
1358 * From here on we assume that the new matrix is different, wherever it matters
1359 * but note
1361 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1362 TRACE("The app is setting the same matrix over again\n");
1363 return D3D_OK;
1364 } else {
1365 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1369 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1370 where ViewMat = Camera space, WorldMat = world space.
1372 In OpenGL, camera and world space is combined into GL_MODELVIEW
1373 matrix. The Projection matrix stay projection matrix.
1376 /* Capture the times we can just ignore the change */
1377 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1378 This->modelview_valid = FALSE;
1379 return D3D_OK;
1381 } else if (d3dts == D3DTS_PROJECTION) {
1382 This->proj_valid = FALSE;
1383 return D3D_OK;
1385 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1386 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1387 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1388 return D3D_OK;
1391 /* Chances are we really are going to have to change a matrix */
1392 ENTER_GL();
1394 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1395 if (d3dts < GL_LIMITS(textures)) {
1396 int tex = d3dts - D3DTS_TEXTURE0;
1397 #if defined(GL_VERSION_1_3)
1398 glActiveTexture(GL_TEXTURE0 + tex);
1399 #else
1400 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1401 #endif
1402 set_texture_matrix((float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1405 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1406 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1407 This->modelview_valid = FALSE;
1408 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1409 glMatrixMode(GL_MODELVIEW);
1410 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1411 glPushMatrix();
1412 glLoadMatrixf((float *)lpmatrix);
1413 checkGLcall("glLoadMatrixf(...)");
1415 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1416 * NOTE: We have to reset the positions even if the light/plane is not currently
1417 * enabled, since the call to enable it will not reset the position.
1418 * NOTE2: Apparently texture transforms do NOT need reapplying
1421 /* Reset lights */
1422 for (k = 0; k < GL_LIMITS(lights); k++) {
1423 glLightfv(GL_LIGHT0 + k, GL_POSITION, This->lightPosn[k]);
1424 checkGLcall("glLightfv posn");
1425 glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, This->lightDirn[k]);
1426 checkGLcall("glLightfv dirn");
1428 /* Reset Clipping Planes if clipping is enabled */
1429 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1430 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1431 checkGLcall("glClipPlane");
1433 glPopMatrix();
1435 } else { /* What was requested!?? */
1436 WARN("invalid matrix specified: %i\n", d3dts);
1440 /* Release lock, all done */
1441 LEAVE_GL();
1442 return D3D_OK;
1445 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1446 ICOM_THIS(IDirect3DDevice8Impl,iface);
1447 TRACE("(%p) : for State %d\n", This, State);
1448 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1449 return D3D_OK;
1452 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1453 D3DMATRIX *mat = NULL;
1454 D3DMATRIX temp;
1456 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1457 but works regardless of recording being on.
1458 If this is found to be wrong, change to StateBlock. */
1459 ICOM_THIS(IDirect3DDevice8Impl,iface);
1460 TRACE("(%p) : For state %u\n", This, State);
1462 if (State < HIGHEST_TRANSFORMSTATE)
1464 mat = &This->UpdateStateBlock->transforms[State];
1465 } else {
1466 FIXME("Unhandled transform state!!\n");
1469 /* Copied from ddraw code: */
1470 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);
1471 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);
1472 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);
1473 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);
1475 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);
1476 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);
1477 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);
1478 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);
1480 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);
1481 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);
1482 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);
1483 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);
1485 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);
1486 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);
1487 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);
1488 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);
1490 /* Apply change via set transform - will reapply to eg. lights this way */
1491 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1492 return D3D_OK;
1494 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1495 ICOM_THIS(IDirect3DDevice8Impl,iface);
1497 TRACE("(%p)\n", This);
1498 This->UpdateStateBlock->Changed.viewport = TRUE;
1499 This->UpdateStateBlock->Set.viewport = TRUE;
1500 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1502 /* Handle recording of state blocks */
1503 if (This->isRecordingState) {
1504 TRACE("Recording... not performing anything\n");
1505 return D3D_OK;
1508 ENTER_GL();
1510 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1511 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1513 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1514 checkGLcall("glDepthRange");
1515 /* Note: GL requires lower left, DirectX supplies upper left */
1516 glViewport(pViewport->X, (This->PresentParms.BackBufferHeight - (pViewport->Y + pViewport->Height)),
1517 pViewport->Width, pViewport->Height);
1518 checkGLcall("glViewport");
1520 LEAVE_GL();
1522 return D3D_OK;
1525 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1526 ICOM_THIS(IDirect3DDevice8Impl,iface);
1527 TRACE("(%p)\n", This);
1528 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1529 return D3D_OK;
1532 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1533 ICOM_THIS(IDirect3DDevice8Impl,iface);
1535 This->UpdateStateBlock->Changed.material = TRUE;
1536 This->UpdateStateBlock->Set.material = TRUE;
1537 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1539 /* Handle recording of state blocks */
1540 if (This->isRecordingState) {
1541 TRACE("Recording... not performing anything\n");
1542 return D3D_OK;
1545 ENTER_GL();
1546 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1547 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1548 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1549 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1550 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1552 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1553 checkGLcall("glMaterialfv");
1554 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1555 checkGLcall("glMaterialfv");
1557 /* Only change material color if specular is enabled, otherwise it is set to black */
1558 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1559 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1560 checkGLcall("glMaterialfv");
1562 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1563 checkGLcall("glMaterialfv");
1564 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1565 checkGLcall("glMaterialf");
1567 LEAVE_GL();
1568 return D3D_OK;
1570 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1571 ICOM_THIS(IDirect3DDevice8Impl,iface);
1572 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1573 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1574 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1575 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1576 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1577 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1578 return D3D_OK;
1581 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1582 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
1583 float rho;
1584 float quad_att;
1586 ICOM_THIS(IDirect3DDevice8Impl,iface);
1587 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1589 if (Index >= GL_LIMITS(lights)) {
1590 TRACE("Cannot handle more lights than device supports\n");
1591 return D3DERR_INVALIDCALL;
1594 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,
1595 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1596 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1597 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1598 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1599 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1600 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1602 This->UpdateStateBlock->Changed.lights[Index] = TRUE;
1603 This->UpdateStateBlock->Set.lights[Index] = TRUE;
1604 memcpy(&This->UpdateStateBlock->lights[Index], pLight, sizeof(D3DLIGHT8));
1606 /* Handle recording of state blocks */
1607 if (This->isRecordingState) {
1608 TRACE("Recording... not performing anything\n");
1609 return D3D_OK;
1612 ENTER_GL();
1614 /* Diffuse: */
1615 colRGBA[0] = pLight->Diffuse.r;
1616 colRGBA[1] = pLight->Diffuse.g;
1617 colRGBA[2] = pLight->Diffuse.b;
1618 colRGBA[3] = pLight->Diffuse.a;
1619 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
1620 checkGLcall("glLightfv");
1622 /* Specular */
1623 colRGBA[0] = pLight->Specular.r;
1624 colRGBA[1] = pLight->Specular.g;
1625 colRGBA[2] = pLight->Specular.b;
1626 colRGBA[3] = pLight->Specular.a;
1627 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
1628 checkGLcall("glLightfv");
1630 /* Ambient */
1631 colRGBA[0] = pLight->Ambient.r;
1632 colRGBA[1] = pLight->Ambient.g;
1633 colRGBA[2] = pLight->Ambient.b;
1634 colRGBA[3] = pLight->Ambient.a;
1635 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
1636 checkGLcall("glLightfv");
1638 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
1639 glMatrixMode(GL_MODELVIEW);
1640 glPushMatrix();
1641 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1643 /* Attenuation - Are these right? guessing... */
1644 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, pLight->Attenuation0);
1645 checkGLcall("glLightf");
1646 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, pLight->Attenuation1);
1647 checkGLcall("glLightf");
1649 quad_att = 1.4/(pLight->Range*pLight->Range);
1650 if (quad_att < pLight->Attenuation2) quad_att = pLight->Attenuation2;
1651 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
1652 checkGLcall("glLightf");
1654 switch (pLight->Type) {
1655 case D3DLIGHT_POINT:
1656 /* Position */
1657 This->lightPosn[Index][0] = pLight->Position.x;
1658 This->lightPosn[Index][1] = pLight->Position.y;
1659 This->lightPosn[Index][2] = pLight->Position.z;
1660 This->lightPosn[Index][3] = 1.0;
1661 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
1662 checkGLcall("glLightfv");
1664 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, 180);
1665 checkGLcall("glLightf");
1667 /* FIXME: Range */
1668 break;
1670 case D3DLIGHT_SPOT:
1671 /* Position */
1672 This->lightPosn[Index][0] = pLight->Position.x;
1673 This->lightPosn[Index][1] = pLight->Position.y;
1674 This->lightPosn[Index][2] = pLight->Position.z;
1675 This->lightPosn[Index][3] = 1.0;
1676 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
1677 checkGLcall("glLightfv");
1679 /* Direction */
1680 This->lightDirn[Index][0] = pLight->Direction.x;
1681 This->lightDirn[Index][1] = pLight->Direction.y;
1682 This->lightDirn[Index][2] = pLight->Direction.z;
1683 This->lightDirn[Index][3] = 1.0;
1684 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &This->lightDirn[Index][0]);
1685 checkGLcall("glLightfv");
1688 * opengl-ish and d3d-ish spot lights use too different models for the
1689 * light "intensity" as a function of the angle towards the main light direction,
1690 * so we only can approximate very roughly.
1691 * however spot lights are rather rarely used in games (if ever used at all).
1692 * furthermore if still used, probably nobody pays attention to such details.
1694 if (pLight->Falloff == 0) {
1695 rho = 6.28f;
1696 } else {
1697 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1699 if (rho < 0.0001) rho = 0.0001f;
1700 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, -0.3/log(cos(rho/2)));
1701 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, pLight->Phi*90/M_PI);
1703 /* FIXME: Range */
1704 break;
1705 case D3DLIGHT_DIRECTIONAL:
1706 /* Direction */
1707 This->lightPosn[Index][0] = -pLight->Direction.x;
1708 This->lightPosn[Index][1] = -pLight->Direction.y;
1709 This->lightPosn[Index][2] = -pLight->Direction.z;
1710 This->lightPosn[Index][3] = 0.0;
1711 glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]); /* Note gl uses w position of 0 for direction! */
1712 checkGLcall("glLightfv");
1714 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f);
1715 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
1718 break;
1719 default:
1720 FIXME("Unrecognized light type %d\n", pLight->Type);
1723 /* Restore the modelview matrix */
1724 glPopMatrix();
1726 LEAVE_GL();
1728 return D3D_OK;
1730 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1731 ICOM_THIS(IDirect3DDevice8Impl,iface);
1732 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1734 if (Index >= GL_LIMITS(lights)) {
1735 TRACE("Cannot handle more lights than device supports\n");
1736 return D3DERR_INVALIDCALL;
1739 memcpy(pLight, &This->StateBlock->lights[Index], sizeof(D3DLIGHT8));
1740 return D3D_OK;
1742 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1743 ICOM_THIS(IDirect3DDevice8Impl,iface);
1744 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1746 if (Index >= GL_LIMITS(lights)) {
1747 TRACE("Cannot handle more lights than device supports\n");
1748 return D3DERR_INVALIDCALL;
1751 This->UpdateStateBlock->Changed.lightEnable[Index] = TRUE;
1752 This->UpdateStateBlock->Set.lightEnable[Index] = TRUE;
1753 This->UpdateStateBlock->lightEnable[Index] = Enable;
1755 /* Handle recording of state blocks */
1756 if (This->isRecordingState) {
1757 TRACE("Recording... not performing anything\n");
1758 return D3D_OK;
1761 ENTER_GL();
1762 if (Enable) {
1763 glEnable(GL_LIGHT0 + Index);
1764 checkGLcall("glEnable GL_LIGHT0+Index");
1765 } else {
1766 glDisable(GL_LIGHT0 + Index);
1767 checkGLcall("glDisable GL_LIGHT0+Index");
1769 LEAVE_GL();
1771 return D3D_OK;
1773 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
1774 ICOM_THIS(IDirect3DDevice8Impl,iface);
1775 TRACE("(%p) : for idx(%ld)\n", This, Index);
1777 if (Index >= GL_LIMITS(lights)) {
1778 TRACE("Cannot handle more lights than device supports\n");
1779 return D3DERR_INVALIDCALL;
1782 *pEnable = This->StateBlock->lightEnable[Index];
1783 return D3D_OK;
1785 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
1786 ICOM_THIS(IDirect3DDevice8Impl,iface);
1787 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
1789 /* Validate Index */
1790 if (Index >= GL_LIMITS(clipplanes)) {
1791 TRACE("Application has requested clipplane this device doesnt support\n");
1792 return D3DERR_INVALIDCALL;
1795 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
1796 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
1797 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
1798 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
1799 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
1800 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
1802 /* Handle recording of state blocks */
1803 if (This->isRecordingState) {
1804 TRACE("Recording... not performing anything\n");
1805 return D3D_OK;
1808 /* Apply it */
1810 ENTER_GL();
1812 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
1813 glMatrixMode(GL_MODELVIEW);
1814 glPushMatrix();
1815 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1817 TRACE("Clipplane [%f,%f,%f,%f]\n",
1818 This->UpdateStateBlock->clipplane[Index][0],
1819 This->UpdateStateBlock->clipplane[Index][1],
1820 This->UpdateStateBlock->clipplane[Index][2],
1821 This->UpdateStateBlock->clipplane[Index][3]);
1822 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
1823 checkGLcall("glClipPlane");
1825 glPopMatrix();
1827 LEAVE_GL();
1829 return D3D_OK;
1831 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
1832 ICOM_THIS(IDirect3DDevice8Impl,iface);
1833 TRACE("(%p) : for idx %ld\n", This, Index);
1835 /* Validate Index */
1836 if (Index >= GL_LIMITS(clipplanes)) {
1837 TRACE("Application has requested clipplane this device doesnt support\n");
1838 return D3DERR_INVALIDCALL;
1841 pPlane[0] = This->StateBlock->clipplane[Index][0];
1842 pPlane[1] = This->StateBlock->clipplane[Index][1];
1843 pPlane[2] = This->StateBlock->clipplane[Index][2];
1844 pPlane[3] = This->StateBlock->clipplane[Index][3];
1845 return D3D_OK;
1847 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
1848 ICOM_THIS(IDirect3DDevice8Impl,iface);
1849 DWORD OldValue = This->StateBlock->renderstate[State];
1851 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
1852 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
1853 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
1854 This->UpdateStateBlock->renderstate[State] = Value;
1856 /* Handle recording of state blocks */
1857 if (This->isRecordingState) {
1858 TRACE("Recording... not performing anything\n");
1859 return D3D_OK;
1862 ENTER_GL();
1864 switch (State) {
1865 case D3DRS_FILLMODE :
1866 switch ((D3DFILLMODE) Value) {
1867 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
1868 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
1869 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
1870 default:
1871 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
1873 checkGLcall("glPolygonMode (fillmode)");
1874 break;
1876 case D3DRS_LIGHTING :
1877 if (Value) {
1878 glEnable(GL_LIGHTING);
1879 checkGLcall("glEnable GL_LIGHTING");
1880 } else {
1881 glDisable(GL_LIGHTING);
1882 checkGLcall("glDisable GL_LIGHTING");
1884 break;
1886 case D3DRS_ZENABLE :
1887 switch ((D3DZBUFFERTYPE) Value) {
1888 case D3DZB_FALSE:
1889 glDisable(GL_DEPTH_TEST);
1890 checkGLcall("glDisable GL_DEPTH_TEST");
1891 break;
1892 case D3DZB_TRUE:
1893 glEnable(GL_DEPTH_TEST);
1894 checkGLcall("glEnable GL_DEPTH_TEST");
1895 break;
1897 case D3DZB_USEW:
1898 default:
1899 FIXME("Unrecognized/Unhandled D3DZBUFFERTYPE value %ld\n", Value);
1901 break;
1903 case D3DRS_CULLMODE :
1905 /* If we are culling "back faces with clockwise vertices" then
1906 set front faces to be counter clockwise and enable culling
1907 of back faces */
1908 switch ((D3DCULL) Value) {
1909 case D3DCULL_NONE:
1910 glDisable(GL_CULL_FACE);
1911 checkGLcall("glDisable GL_CULL_FACE");
1912 break;
1913 case D3DCULL_CW:
1914 glEnable(GL_CULL_FACE);
1915 checkGLcall("glEnable GL_CULL_FACE");
1916 glFrontFace(GL_CCW);
1917 checkGLcall("glFrontFace GL_CCW");
1918 glCullFace(GL_BACK);
1919 break;
1920 case D3DCULL_CCW:
1921 glEnable(GL_CULL_FACE);
1922 checkGLcall("glEnable GL_CULL_FACE");
1923 glFrontFace(GL_CW);
1924 checkGLcall("glFrontFace GL_CW");
1925 glCullFace(GL_BACK);
1926 break;
1927 default:
1928 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
1930 break;
1932 case D3DRS_SHADEMODE :
1933 switch ((D3DSHADEMODE) Value) {
1934 case D3DSHADE_FLAT:
1935 glShadeModel(GL_FLAT);
1936 checkGLcall("glShadeModel");
1937 break;
1938 case D3DSHADE_GOURAUD:
1939 glShadeModel(GL_SMOOTH);
1940 checkGLcall("glShadeModel");
1941 break;
1942 case D3DSHADE_PHONG:
1943 FIXME("D3DSHADE_PHONG isnt supported?\n");
1945 LEAVE_GL();
1946 return D3DERR_INVALIDCALL;
1947 default:
1948 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
1950 break;
1952 case D3DRS_DITHERENABLE :
1953 if (Value) {
1954 glEnable(GL_DITHER);
1955 checkGLcall("glEnable GL_DITHER");
1956 } else {
1957 glDisable(GL_DITHER);
1958 checkGLcall("glDisable GL_DITHER");
1960 break;
1962 case D3DRS_ZWRITEENABLE :
1963 if (Value) {
1964 glDepthMask(1);
1965 checkGLcall("glDepthMask");
1966 } else {
1967 glDepthMask(0);
1968 checkGLcall("glDepthMask");
1970 break;
1972 case D3DRS_ZFUNC :
1974 int glParm = GL_LESS;
1976 switch ((D3DCMPFUNC) Value) {
1977 case D3DCMP_NEVER: glParm=GL_NEVER; break;
1978 case D3DCMP_LESS: glParm=GL_LESS; break;
1979 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
1980 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
1981 case D3DCMP_GREATER: glParm=GL_GREATER; break;
1982 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
1983 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
1984 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
1985 default:
1986 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
1988 glDepthFunc(glParm);
1989 checkGLcall("glDepthFunc");
1991 break;
1993 case D3DRS_AMBIENT :
1995 float col[4];
1996 D3DCOLORTOGLFLOAT4(Value, col);
1997 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
1998 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
1999 checkGLcall("glLightModel for MODEL_AMBIENT");
2002 break;
2004 case D3DRS_ALPHABLENDENABLE :
2005 if (Value) {
2006 glEnable(GL_BLEND);
2007 checkGLcall("glEnable GL_BLEND");
2008 } else {
2009 glDisable(GL_BLEND);
2010 checkGLcall("glDisable GL_BLEND");
2012 break;
2014 case D3DRS_SRCBLEND :
2015 case D3DRS_DESTBLEND :
2017 int newVal = GL_ZERO;
2018 switch (Value) {
2019 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2020 case D3DBLEND_ONE : newVal = GL_ONE; break;
2021 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2022 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2023 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2024 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2025 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2026 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2027 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2028 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2029 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2031 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2032 This->srcBlend = newVal;
2033 This->dstBlend = newVal;
2034 break;
2036 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2037 This->srcBlend = newVal;
2038 This->dstBlend = newVal;
2039 break;
2040 default:
2041 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2044 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2045 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2046 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2047 glBlendFunc(This->srcBlend, This->dstBlend);
2049 checkGLcall("glBlendFunc");
2051 break;
2053 case D3DRS_ALPHATESTENABLE :
2054 if (Value) {
2055 glEnable(GL_ALPHA_TEST);
2056 checkGLcall("glEnable GL_ALPHA_TEST");
2057 } else {
2058 glDisable(GL_ALPHA_TEST);
2059 checkGLcall("glDisable GL_ALPHA_TEST");
2061 break;
2063 case D3DRS_ALPHAFUNC :
2065 int glParm = GL_LESS;
2066 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2068 switch ((D3DCMPFUNC) Value) {
2069 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2070 case D3DCMP_LESS: glParm = GL_LESS; break;
2071 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2072 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2073 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2074 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2075 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2076 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2077 default:
2078 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2080 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2081 glAlphaFunc(glParm, ref);
2082 This->alphafunc = glParm;
2083 checkGLcall("glAlphaFunc");
2085 break;
2087 case D3DRS_ALPHAREF :
2089 int glParm = This->alphafunc;
2090 float ref = 1.0f;
2092 ref = ((float) Value) / 255.0f;
2093 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2094 glAlphaFunc(glParm, ref);
2095 checkGLcall("glAlphaFunc");
2097 break;
2099 case D3DRS_CLIPPLANEENABLE :
2100 case D3DRS_CLIPPING :
2102 /* Ensure we only do the changed clip planes */
2103 DWORD enable = 0xFFFFFFFF;
2104 DWORD disable = 0x00000000;
2106 /* If enabling / disabling all */
2107 if (State == D3DRS_CLIPPING) {
2108 if (Value) {
2109 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2110 disable = 0x00;
2111 } else {
2112 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2113 enable = 0x00;
2115 } else {
2116 enable = Value & ~OldValue;
2117 disable = ~Value & OldValue;
2120 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2121 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2122 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2123 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2124 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2125 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2127 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2128 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2129 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2130 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2131 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2132 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2134 break;
2136 case D3DRS_BLENDOP :
2138 int glParm = GL_FUNC_ADD;
2140 switch ((D3DBLENDOP) Value) {
2141 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2142 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2143 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2144 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2145 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2146 default:
2147 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2149 TRACE("glBlendEquation(%x)\n", glParm);
2150 glBlendEquation(glParm);
2151 checkGLcall("glBlendEquation");
2153 break;
2155 case D3DRS_TEXTUREFACTOR :
2157 int i;
2159 /* Note the texture color applies to all textures whereas
2160 GL_TEXTURE_ENV_COLOR applies to active only */
2161 float col[4];
2162 D3DCOLORTOGLFLOAT4(Value, col);
2163 /* Set the default alpha blend color */
2164 glBlendColor(col[0], col[1], col[2], col[3]);
2165 checkGLcall("glBlendColor");
2167 /* And now the default texture color as well */
2168 for (i = 0; i < GL_LIMITS(textures); i++) {
2170 /* Note the D3DRS value applies to all textures, but GL has one
2171 per texture, so apply it now ready to be used! */
2172 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2173 #if defined(GL_VERSION_1_3)
2174 glActiveTexture(GL_TEXTURE0 + i);
2175 #else
2176 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2177 #endif
2178 checkGLcall("Activate texture.. to update const color");
2179 } else if (i>0) {
2180 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2183 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2184 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2187 break;
2189 case D3DRS_SPECULARENABLE :
2191 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2192 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2193 specular color. This is wrong:
2194 Separate specular color means the specular colour is maintained separately, whereas
2195 single color means it is merged in. However in both cases they are being used to
2196 some extent.
2197 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2198 NOTE: If not supported dont give FIXME as very minimal impact and very few people are
2199 yet running 1.4!
2201 if (Value) {
2202 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2203 checkGLcall("glMaterialfv");
2204 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2205 glEnable(GL_COLOR_SUM_EXT);
2206 } else {
2207 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2209 checkGLcall("glEnable(GL_COLOR_SUM)");
2210 } else {
2211 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2213 /* for the case of enabled lighting: */
2214 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2215 checkGLcall("glMaterialfv");
2217 /* for the case of disabled lighting: */
2218 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2219 glDisable(GL_COLOR_SUM_EXT);
2220 } else {
2221 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2223 checkGLcall("glDisable(GL_COLOR_SUM)");
2226 break;
2228 case D3DRS_STENCILENABLE :
2229 if (Value) {
2230 glEnable(GL_STENCIL_TEST);
2231 checkGLcall("glEnable GL_STENCIL_TEST");
2232 } else {
2233 glDisable(GL_STENCIL_TEST);
2234 checkGLcall("glDisable GL_STENCIL_TEST");
2236 break;
2238 case D3DRS_STENCILFUNC :
2240 int glParm = GL_ALWAYS;
2241 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2242 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2244 switch ((D3DCMPFUNC) Value) {
2245 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2246 case D3DCMP_LESS: glParm=GL_LESS; break;
2247 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2248 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2249 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2250 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2251 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2252 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2253 default:
2254 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2256 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2257 This->stencilfunc = glParm;
2258 glStencilFunc(glParm, ref, mask);
2259 checkGLcall("glStencilFunc");
2261 break;
2263 case D3DRS_STENCILREF :
2265 int glParm = This->stencilfunc;
2266 int ref = 0;
2267 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2269 ref = Value;
2270 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2271 glStencilFunc(glParm, ref, mask);
2272 checkGLcall("glStencilFunc");
2274 break;
2276 case D3DRS_STENCILMASK :
2278 int glParm = This->stencilfunc;
2279 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2280 GLuint mask = Value;
2282 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2283 glStencilFunc(glParm, ref, mask);
2284 checkGLcall("glStencilFunc");
2286 break;
2288 case D3DRS_STENCILFAIL :
2290 GLenum fail ;
2291 GLenum zpass ;
2292 GLenum zfail ;
2294 fail = StencilOp(Value);
2295 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2296 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2297 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2298 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2300 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2301 glStencilOp(fail, zfail, zpass);
2302 checkGLcall("glStencilOp(fail, zfail, zpass);");
2304 break;
2305 case D3DRS_STENCILZFAIL :
2307 GLenum fail ;
2308 GLenum zpass ;
2309 GLenum zfail ;
2311 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2312 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2313 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2314 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2315 zfail = StencilOp(Value);
2317 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2318 glStencilOp(fail, zfail, zpass);
2319 checkGLcall("glStencilOp(fail, zfail, zpass);");
2321 break;
2322 case D3DRS_STENCILPASS :
2324 GLenum fail ;
2325 GLenum zpass ;
2326 GLenum zfail ;
2328 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2329 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2330 zpass = StencilOp(Value);
2331 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2332 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2334 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2335 glStencilOp(fail, zfail, zpass);
2336 checkGLcall("glStencilOp(fail, zfail, zpass);");
2338 break;
2340 case D3DRS_STENCILWRITEMASK :
2342 glStencilMask(Value);
2343 TRACE("glStencilMask(%lu)\n", Value);
2344 checkGLcall("glStencilMask");
2346 break;
2348 case D3DRS_FOGENABLE :
2350 if (Value && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE) {
2351 glEnable(GL_FOG);
2352 checkGLcall("glEnable GL_FOG");
2353 } else {
2354 glDisable(GL_FOG);
2355 checkGLcall("glDisable GL_FOG");
2358 break;
2360 case D3DRS_FOGCOLOR :
2362 float col[4];
2363 D3DCOLORTOGLFLOAT4(Value, col);
2364 /* Set the default alpha blend color */
2365 glFogfv(GL_FOG_COLOR, &col[0]);
2366 checkGLcall("glFog GL_FOG_COLOR");
2368 break;
2370 case D3DRS_FOGTABLEMODE :
2372 switch (Value) {
2373 case D3DFOG_NONE: /* I don't know what to do here */ break;
2374 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2375 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2376 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2377 default:
2378 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2381 break;
2383 case D3DRS_FOGSTART :
2385 float *f = (float*) &Value;
2386 glFogfv(GL_FOG_START, f);
2387 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2388 TRACE("Fog Start == %f\n", *f);
2390 break;
2392 case D3DRS_FOGEND :
2394 float *f = (float*) &Value;
2395 glFogfv(GL_FOG_END, f);
2396 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2397 TRACE("Fog End == %f\n", *f);
2399 break;
2401 case D3DRS_FOGDENSITY :
2403 float *f = (float*) &Value;
2404 glFogfv(GL_FOG_DENSITY, f);
2405 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2407 break;
2409 case D3DRS_VERTEXBLEND :
2411 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2412 TRACE("Vertex Blending state to %ld\n", Value);
2414 break;
2416 case D3DRS_TWEENFACTOR :
2418 This->UpdateStateBlock->tween_factor = *((float*) &Value);
2419 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2421 break;
2423 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2425 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2427 break;
2429 case D3DRS_COLORVERTEX :
2430 case D3DRS_DIFFUSEMATERIALSOURCE :
2431 case D3DRS_SPECULARMATERIALSOURCE :
2432 case D3DRS_AMBIENTMATERIALSOURCE :
2433 case D3DRS_EMISSIVEMATERIALSOURCE :
2435 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2437 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2438 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2439 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2440 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2441 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2442 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2444 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2445 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2446 Parm = GL_AMBIENT_AND_DIFFUSE;
2447 } else {
2448 Parm = GL_DIFFUSE;
2450 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2451 Parm = GL_AMBIENT;
2452 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2453 Parm = GL_EMISSION;
2454 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2455 Parm = GL_SPECULAR;
2456 } else {
2457 Parm = -1;
2460 if (Parm == -1) {
2461 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2462 } else {
2463 This->tracking_color = NEEDS_TRACKING;
2464 This->tracking_parm = Parm;
2467 } else {
2468 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2471 break;
2473 case D3DRS_LINEPATTERN :
2475 D3DLINEPATTERN *pattern = (D3DLINEPATTERN *)&Value;
2476 TRACE("Line pattern: repeat %d bits %x\n", pattern->wRepeatFactor, pattern->wLinePattern);
2478 if (pattern->wRepeatFactor) {
2479 glLineStipple(pattern->wRepeatFactor, pattern->wLinePattern);
2480 checkGLcall("glLineStipple(repeat, linepattern)");
2481 glEnable(GL_LINE_STIPPLE);
2482 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2483 } else {
2484 glDisable(GL_LINE_STIPPLE);
2485 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2488 break;
2490 case D3DRS_ZBIAS :
2492 if (Value) {
2493 TRACE("ZBias value %f\n", *((float*)&Value));
2494 glPolygonOffset(0, -*((float*)&Value));
2495 checkGLcall("glPolygonOffset(0, -Value)");
2496 glEnable(GL_POLYGON_OFFSET_FILL);
2497 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2498 glEnable(GL_POLYGON_OFFSET_LINE);
2499 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2500 glEnable(GL_POLYGON_OFFSET_POINT);
2501 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2502 } else {
2503 glDisable(GL_POLYGON_OFFSET_FILL);
2504 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2505 glDisable(GL_POLYGON_OFFSET_LINE);
2506 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2507 glDisable(GL_POLYGON_OFFSET_POINT);
2508 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2511 break;
2513 case D3DRS_NORMALIZENORMALS :
2514 if (Value) {
2515 glEnable(GL_NORMALIZE);
2516 checkGLcall("glEnable(GL_NORMALIZE);");
2517 } else {
2518 glDisable(GL_NORMALIZE);
2519 checkGLcall("glDisable(GL_NORMALIZE);");
2521 break;
2523 case D3DRS_POINTSIZE :
2524 TRACE("Set point size to %f\n", *((float*)&Value));
2525 glPointSize(*((float*)&Value));
2526 checkGLcall("glPointSize(...);");
2527 break;
2529 case D3DRS_POINTSIZE_MIN :
2530 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2531 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, *((float*)&Value));
2532 checkGLcall("glPointParameterfEXT(...);");
2533 } else {
2534 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2536 break;
2538 case D3DRS_POINTSIZE_MAX :
2539 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2540 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, *((float*)&Value));
2541 checkGLcall("glPointParameterfEXT(...);");
2542 } else {
2543 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2545 break;
2547 case D3DRS_POINTSCALE_A :
2548 case D3DRS_POINTSCALE_B :
2549 case D3DRS_POINTSCALE_C :
2550 case D3DRS_POINTSCALEENABLE :
2552 /* If enabled, supply the parameters, otherwise fall back to defaults */
2553 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2554 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2555 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2556 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2557 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2559 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2560 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2561 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2562 } else {
2563 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2565 } else {
2566 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2567 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2568 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2569 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2570 } else {
2571 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2574 break;
2577 case D3DRS_COLORWRITEENABLE :
2578 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2579 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2580 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2581 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2582 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2583 glColorMask(Value & D3DCOLORWRITEENABLE_RED,
2584 Value & D3DCOLORWRITEENABLE_GREEN,
2585 Value & D3DCOLORWRITEENABLE_BLUE,
2586 Value & D3DCOLORWRITEENABLE_ALPHA);
2587 checkGLcall("glColorMask(...)");
2588 break;
2590 /* Unhandled yet...! */
2591 case D3DRS_LASTPIXEL :
2592 case D3DRS_ZVISIBLE :
2593 case D3DRS_EDGEANTIALIAS :
2594 case D3DRS_RANGEFOGENABLE :
2595 case D3DRS_WRAP0 :
2596 case D3DRS_WRAP1 :
2597 case D3DRS_WRAP2 :
2598 case D3DRS_WRAP3 :
2599 case D3DRS_WRAP4 :
2600 case D3DRS_WRAP5 :
2601 case D3DRS_WRAP6 :
2602 case D3DRS_WRAP7 :
2603 case D3DRS_FOGVERTEXMODE :
2604 case D3DRS_LOCALVIEWER :
2605 case D3DRS_SOFTWAREVERTEXPROCESSING :
2606 case D3DRS_POINTSPRITEENABLE :
2607 case D3DRS_MULTISAMPLEANTIALIAS :
2608 case D3DRS_MULTISAMPLEMASK :
2609 case D3DRS_PATCHEDGESTYLE :
2610 case D3DRS_PATCHSEGMENTS :
2611 case D3DRS_DEBUGMONITORTOKEN :
2612 case D3DRS_POSITIONORDER :
2613 case D3DRS_NORMALORDER :
2614 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2615 TRACE("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2616 break;
2617 default:
2618 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2621 LEAVE_GL();
2623 return D3D_OK;
2625 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2626 ICOM_THIS(IDirect3DDevice8Impl,iface);
2627 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2628 *pValue = This->StateBlock->renderstate[State];
2629 return D3D_OK;
2631 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2632 ICOM_THIS(IDirect3DDevice8Impl,iface);
2634 TRACE("(%p)\n", This);
2636 return IDirect3DDeviceImpl_BeginStateBlock(This);
2638 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2639 IDirect3DStateBlockImpl* pSB;
2640 ICOM_THIS(IDirect3DDevice8Impl,iface);
2641 HRESULT res;
2643 TRACE("(%p)\n", This);
2645 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2646 *pToken = (DWORD) pSB;
2647 return res;
2650 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2651 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2652 ICOM_THIS(IDirect3DDevice8Impl,iface);
2654 TRACE("(%p)\n", This);
2656 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2659 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2660 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2661 ICOM_THIS(IDirect3DDevice8Impl,iface);
2663 TRACE("(%p)\n", This);
2665 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2667 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2668 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2669 ICOM_THIS(IDirect3DDevice8Impl,iface);
2671 TRACE("(%p)\n", This);
2673 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
2676 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
2677 IDirect3DStateBlockImpl* pSB;
2678 ICOM_THIS(IDirect3DDevice8Impl,iface);
2679 HRESULT res;
2681 TRACE("(%p) : for type %d\n", This, Type);
2683 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
2684 *pToken = (DWORD) pSB;
2685 return res;
2688 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
2689 ICOM_THIS(IDirect3DDevice8Impl,iface);
2690 FIXME("(%p) : stub\n", This); return D3D_OK;
2692 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
2693 ICOM_THIS(IDirect3DDevice8Impl,iface);
2694 FIXME("(%p) : stub\n", This); return D3D_OK;
2696 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
2697 ICOM_THIS(IDirect3DDevice8Impl,iface);
2698 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
2699 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
2700 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
2701 return D3D_OK;
2703 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
2705 IDirect3DBaseTexture8 *oldTxt;
2706 BOOL reapplyStates = TRUE;
2707 DWORD oldTextureDimensions = -1;
2708 DWORD reapplyFlags = 0;
2710 ICOM_THIS(IDirect3DDevice8Impl,iface);
2711 D3DRESOURCETYPE textureType;
2713 oldTxt = This->UpdateStateBlock->textures[Stage];
2714 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
2716 /* Reject invalid texture units */
2717 if (Stage >= GL_LIMITS(textures)) {
2718 TRACE("Attempt to access invalid texture rejected\n");
2719 return D3DERR_INVALIDCALL;
2722 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
2723 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
2724 This->UpdateStateBlock->textures[Stage] = pTexture;
2726 /* Handle recording of state blocks */
2727 if (This->isRecordingState) {
2728 TRACE("Recording... not performing anything\n");
2729 return D3D_OK;
2732 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
2733 ENTER_GL();
2735 /* Make appropriate texture active */
2736 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2737 #if defined(GL_VERSION_1_3)
2738 glActiveTexture(GL_TEXTURE0 + Stage);
2739 #else
2740 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2741 #endif
2742 checkGLcall("glActiveTextureARB");
2743 } else if (Stage>0) {
2744 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2747 /* Decrement the count of the previous texture */
2748 if (NULL != oldTxt) {
2749 IDirect3DBaseTexture8Impl_Release(oldTxt);
2752 if (NULL != pTexture) {
2753 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
2755 /* Now setup the texture appropraitly */
2756 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
2758 if (textureType == D3DRTYPE_TEXTURE) {
2759 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
2760 TRACE("Skipping setting texture as old == new\n");
2761 reapplyStates = FALSE;
2762 } else {
2763 /* Standard 2D texture */
2764 TRACE("Standard 2d texture\n");
2765 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
2767 /* Load up the texture now */
2768 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
2770 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
2771 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
2772 TRACE("Skipping setting texture as old == new\n");
2773 reapplyStates = FALSE;
2774 } else {
2775 /* Standard 3D (volume) texture */
2776 TRACE("Standard 3d texture\n");
2777 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
2779 /* Load up the texture now */
2780 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
2782 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
2783 if (oldTxt == pTexture && TRUE == IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
2784 TRACE("Skipping setting texture as old == new\n");
2785 reapplyStates = FALSE;
2786 } else {
2787 /* Standard Cube texture */
2788 TRACE("Standard Cube texture\n");
2789 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
2791 /* Load up the texture now */
2792 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
2794 } else {
2795 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
2797 } else {
2798 TRACE("Setting to no texture (ie default texture)\n");
2799 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
2800 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
2801 checkGLcall("glBindTexture");
2802 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
2805 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
2806 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
2807 glDisable(oldTextureDimensions);
2808 checkGLcall("Disable oldTextureDimensions");
2809 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
2810 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
2811 checkGLcall("Disable new texture dimensions");
2814 /* If Alpha arg1 is texture then handle the special case when there changes between a
2815 texture and no texture - See comments in set_tex_op */
2816 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
2817 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
2819 reapplyFlags |= REAPPLY_ALPHAOP;
2824 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
2825 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
2826 if (reapplyStates) {
2827 setupTextureStates(iface, Stage, reapplyFlags);
2830 LEAVE_GL();
2832 return D3D_OK;
2835 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
2836 ICOM_THIS(IDirect3DDevice8Impl,iface);
2837 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
2838 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
2839 return D3D_OK;
2842 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
2843 ICOM_THIS(IDirect3DDevice8Impl,iface);
2845 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
2847 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
2849 /* Reject invalid texture units */
2850 if (Stage >= GL_LIMITS(textures)) {
2851 TRACE("Attempt to access invalid texture rejected\n");
2852 return D3DERR_INVALIDCALL;
2855 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
2856 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
2857 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
2859 /* Handle recording of state blocks */
2860 if (This->isRecordingState) {
2861 TRACE("Recording... not performing anything\n");
2862 return D3D_OK;
2865 ENTER_GL();
2867 /* Make appropriate texture active */
2868 VTRACE(("Activating appropriate texture state %ld\n", Stage));
2869 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2870 #if defined(GL_VERSION_1_3)
2871 glActiveTexture(GL_TEXTURE0 + Stage);
2872 vcheckGLcall("glActiveTexture");
2873 #else
2874 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
2875 vcheckGLcall("glActiveTextureARB");
2876 #endif
2877 } else if (Stage > 0) {
2878 FIXME("Program using multiple concurrent textures which this opengl implementation doesnt support\n");
2881 switch (Type) {
2883 case D3DTSS_MINFILTER :
2884 case D3DTSS_MIPFILTER :
2886 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
2887 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
2888 GLint realVal = GL_LINEAR;
2890 if (ValueMIN == D3DTEXF_POINT) {
2891 /* GL_NEAREST_* */
2892 if (ValueMIP == D3DTEXF_POINT) {
2893 realVal = GL_NEAREST_MIPMAP_NEAREST;
2894 } else if (ValueMIP == D3DTEXF_LINEAR) {
2895 realVal = GL_NEAREST_MIPMAP_LINEAR;
2896 } else if (ValueMIP == D3DTEXF_NONE) {
2897 realVal = GL_NEAREST;
2898 } else {
2899 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2900 realVal = GL_NEAREST_MIPMAP_LINEAR;
2902 } else if (ValueMIN == D3DTEXF_LINEAR) {
2903 /* GL_LINEAR_* */
2904 if (ValueMIP == D3DTEXF_POINT) {
2905 realVal = GL_LINEAR_MIPMAP_NEAREST;
2906 } else if (ValueMIP == D3DTEXF_LINEAR) {
2907 realVal = GL_LINEAR_MIPMAP_LINEAR;
2908 } else if (ValueMIP == D3DTEXF_NONE) {
2909 realVal = GL_LINEAR;
2910 } else {
2911 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
2912 realVal = GL_LINEAR_MIPMAP_LINEAR;
2914 } else if (ValueMIN == D3DTEXF_NONE) {
2915 /* Doesnt really make sense - Windows just seems to disable
2916 mipmapping when this occurs */
2917 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
2918 realVal = GL_LINEAR;
2920 } else {
2921 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
2922 realVal = GL_LINEAR_MIPMAP_LINEAR;
2925 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
2926 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
2927 checkGLcall("glTexParameter GL_TEXTURE_MINFILTER, ...");
2929 break;
2931 case D3DTSS_MAXANISOTROPY :
2933 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
2934 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAX_ANISOTROPY_EXT, This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
2935 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
2938 break;
2940 case D3DTSS_MAGFILTER :
2941 if (Value == D3DTEXF_POINT) {
2942 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2943 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_NEAREST");
2944 } else if (Value == D3DTEXF_LINEAR) {
2945 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, GL_LINEAR);
2946 checkGLcall("glTexParameter GL_TEXTURE_MAGFILTER, GL_LINEAR");
2947 } else {
2948 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", Value);
2950 break;
2952 case D3DTSS_ALPHAOP :
2953 case D3DTSS_COLOROP :
2956 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
2957 /* TODO: Disable by making this and all later levels disabled */
2958 glDisable(GL_TEXTURE_1D);
2959 checkGLcall("Disable GL_TEXTURE_1D");
2960 glDisable(GL_TEXTURE_2D);
2961 checkGLcall("Disable GL_TEXTURE_2D");
2962 glDisable(GL_TEXTURE_3D);
2963 checkGLcall("Disable GL_TEXTURE_3D");
2964 break; /* Dont bother setting the texture operations */
2965 } else {
2966 /* Enable only the appropriate texture dimension */
2967 if (Type == D3DTSS_COLOROP) {
2968 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
2969 glEnable(GL_TEXTURE_1D);
2970 checkGLcall("Enable GL_TEXTURE_1D");
2971 } else {
2972 glDisable(GL_TEXTURE_1D);
2973 checkGLcall("Disable GL_TEXTURE_1D");
2975 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
2976 glEnable(GL_TEXTURE_2D);
2977 checkGLcall("Enable GL_TEXTURE_2D");
2978 } else {
2979 glDisable(GL_TEXTURE_2D);
2980 checkGLcall("Disable GL_TEXTURE_2D");
2982 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
2983 glEnable(GL_TEXTURE_3D);
2984 checkGLcall("Enable GL_TEXTURE_3D");
2985 } else {
2986 glDisable(GL_TEXTURE_3D);
2987 checkGLcall("Disable GL_TEXTURE_3D");
2989 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
2990 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
2991 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
2992 } else {
2993 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2994 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
2998 /* Drop through... (Except disable case) */
2999 case D3DTSS_COLORARG0 :
3000 case D3DTSS_COLORARG1 :
3001 case D3DTSS_COLORARG2 :
3002 case D3DTSS_ALPHAARG0 :
3003 case D3DTSS_ALPHAARG1 :
3004 case D3DTSS_ALPHAARG2 :
3006 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3007 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3008 if (isAlphaArg) {
3009 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3010 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3011 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3012 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3013 } else {
3014 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3015 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3016 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3017 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3020 break;
3023 case D3DTSS_ADDRESSU :
3024 case D3DTSS_ADDRESSV :
3025 case D3DTSS_ADDRESSW :
3027 GLint wrapParm = GL_REPEAT;
3028 switch (Value) {
3029 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3030 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3031 case D3DTADDRESS_BORDER: wrapParm = GL_REPEAT; break; /* FIXME: Not right, but better */
3032 #if defined(GL_VERSION_1_4)
3033 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT; break;
3034 #elif defined(GL_ARB_texture_mirrored_repeat)
3035 case D3DTADDRESS_MIRROR: wrapParm = GL_MIRRORED_REPEAT_ARB; break;
3036 #else
3037 case D3DTADDRESS_MIRROR: /* Unsupported in OpenGL pre-1.4 */
3038 #endif
3039 case D3DTADDRESS_MIRRORONCE: /* Unsupported in OpenGL */
3040 default:
3041 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3042 wrapParm = GL_REPEAT;
3045 switch (Type) {
3046 case D3DTSS_ADDRESSU:
3047 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3048 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3049 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3050 break;
3051 case D3DTSS_ADDRESSV:
3052 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3053 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3054 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3055 break;
3056 case D3DTSS_ADDRESSW:
3057 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3058 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3059 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3060 break;
3061 default: /* nop */
3062 break; /** stupic compilator */
3065 break;
3067 case D3DTSS_BORDERCOLOR :
3069 float col[4];
3070 D3DCOLORTOGLFLOAT4(Value, col);
3071 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3072 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3073 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3075 break;
3077 case D3DTSS_TEXCOORDINDEX :
3079 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3081 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3082 one flag, you can still specify an index value, which the system uses to
3083 determine the texture wrapping mode.
3084 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3085 means use the vertex position (camera-space) as the input texture coordinates
3086 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3087 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3088 to the TEXCOORDINDEX value */
3090 /**
3091 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3093 switch (Value & 0xFFFF0000) {
3094 case D3DTSS_TCI_PASSTHRU:
3095 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3096 glDisable(GL_TEXTURE_GEN_S);
3097 glDisable(GL_TEXTURE_GEN_T);
3098 glDisable(GL_TEXTURE_GEN_R);
3099 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3100 break;
3102 case D3DTSS_TCI_CAMERASPACEPOSITION:
3103 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3104 as the input texture coordinates for this stage's texture transformation. This
3105 equates roughly to EYE_LINEAR */
3107 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3108 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3109 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3110 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3111 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3113 glMatrixMode(GL_MODELVIEW);
3114 glPushMatrix();
3115 glLoadIdentity();
3116 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3117 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3118 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3119 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3120 glPopMatrix();
3122 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3123 glEnable(GL_TEXTURE_GEN_S);
3124 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3125 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3126 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3127 glEnable(GL_TEXTURE_GEN_T);
3128 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3129 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3130 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3131 glEnable(GL_TEXTURE_GEN_R);
3132 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3133 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3134 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3136 break;
3138 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3139 case D3DTSS_TCI_CAMERASPACENORMAL:
3141 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3142 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3143 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3144 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3145 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3147 glMatrixMode(GL_MODELVIEW);
3148 glPushMatrix();
3149 glLoadIdentity();
3150 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3151 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3152 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3153 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3154 glPopMatrix();
3156 glEnable(GL_TEXTURE_GEN_S);
3157 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3158 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3159 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3160 glEnable(GL_TEXTURE_GEN_T);
3161 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3162 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3163 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3164 glEnable(GL_TEXTURE_GEN_R);
3165 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3166 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB);
3167 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_ARB)");
3169 break;
3170 #endif
3172 #if defined(GL_ARB_texture_cube_map) || defined(GL_NV_texgen_reflection)
3173 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3176 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3177 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3178 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3179 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3180 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3182 glMatrixMode(GL_MODELVIEW);
3183 glPushMatrix();
3184 glLoadIdentity();
3185 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3186 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3187 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3188 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3189 glPopMatrix();
3191 glEnable(GL_TEXTURE_GEN_S);
3192 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3193 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3194 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3195 glEnable(GL_TEXTURE_GEN_T);
3196 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3197 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3198 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3199 glEnable(GL_TEXTURE_GEN_R);
3200 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3201 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB);
3202 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_ARB)");
3204 break;
3205 #endif
3207 /* Unhandled types: */
3208 default:
3209 /* Todo: */
3210 /* ? disable GL_TEXTURE_GEN_n ? */
3211 glDisable(GL_TEXTURE_GEN_S);
3212 glDisable(GL_TEXTURE_GEN_T);
3213 glDisable(GL_TEXTURE_GEN_R);
3214 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3215 break;
3218 break;
3220 /* Unhandled */
3221 case D3DTSS_BUMPENVMAT00 :
3222 case D3DTSS_BUMPENVMAT01 :
3223 TRACE("BUMPENVMAT0%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3224 break;
3225 case D3DTSS_BUMPENVMAT10 :
3226 case D3DTSS_BUMPENVMAT11 :
3227 TRACE("BUMPENVMAT1%u Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3228 break;
3230 case D3DTSS_TEXTURETRANSFORMFLAGS :
3231 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3232 break;
3234 case D3DTSS_MIPMAPLODBIAS :
3235 case D3DTSS_MAXMIPLEVEL :
3236 case D3DTSS_BUMPENVLSCALE :
3237 case D3DTSS_BUMPENVLOFFSET :
3238 case D3DTSS_RESULTARG :
3239 default:
3240 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3241 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3244 LEAVE_GL();
3246 return D3D_OK;
3248 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3249 ICOM_THIS(IDirect3DDevice8Impl,iface);
3250 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3251 return D3D_OK;
3253 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3254 ICOM_THIS(IDirect3DDevice8Impl,iface);
3255 FIXME("(%p) : stub\n", This);
3256 return D3D_OK;
3258 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3259 ICOM_THIS(IDirect3DDevice8Impl,iface);
3260 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3261 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3262 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3263 return D3D_OK;
3265 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3266 ICOM_THIS(IDirect3DDevice8Impl,iface);
3267 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3268 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3269 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3270 return D3D_OK;
3272 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3273 ICOM_THIS(IDirect3DDevice8Impl,iface);
3274 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3275 This->currentPalette = PaletteNumber;
3277 #if defined(GL_EXT_paletted_texture)
3278 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3280 ENTER_GL();
3282 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3283 GL_RGBA, /* internal format */
3284 256, /* table size */
3285 GL_RGBA, /* table format */
3286 GL_UNSIGNED_BYTE, /* table type */
3287 This->palettes[PaletteNumber]);
3288 checkGLcall("glColorTableEXT");
3290 LEAVE_GL();
3292 } else {
3293 /* Delayed palette handling ... waiting for software emulation into preload code */
3295 #endif
3296 return D3D_OK;
3298 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3299 ICOM_THIS(IDirect3DDevice8Impl,iface);
3300 *PaletteNumber = This->currentPalette;
3301 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3302 return D3D_OK;
3304 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3306 ICOM_THIS(IDirect3DDevice8Impl,iface);
3307 This->StateBlock->streamIsUP = FALSE;
3309 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3310 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3312 return D3D_OK;
3314 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3315 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3316 UINT idxStride = 2;
3317 IDirect3DIndexBuffer8 *pIB;
3318 D3DINDEXBUFFER_DESC IdxBufDsc;
3320 ICOM_THIS(IDirect3DDevice8Impl,iface);
3321 pIB = This->StateBlock->pIndexData;
3322 This->StateBlock->streamIsUP = FALSE;
3324 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3325 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3326 minIndex, NumVertices, startIndex, primCount);
3328 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3329 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3330 idxStride = 2;
3331 } else {
3332 idxStride = 4;
3335 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3336 minIndex);
3338 return D3D_OK;
3340 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3341 ICOM_THIS(IDirect3DDevice8Impl,iface);
3343 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3344 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3346 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3348 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3349 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3350 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3351 This->StateBlock->streamIsUP = TRUE;
3352 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3353 This->StateBlock->stream_stride[0] = 0;
3354 This->StateBlock->stream_source[0] = NULL;
3356 /*stream zero settings set to null at end */
3357 return D3D_OK;
3359 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3360 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3361 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3362 UINT VertexStreamZeroStride) {
3363 int idxStride;
3364 ICOM_THIS(IDirect3DDevice8Impl,iface);
3365 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),
3366 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3368 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3369 if (IndexDataFormat == D3DFMT_INDEX16) {
3370 idxStride = 2;
3371 } else {
3372 idxStride = 4;
3375 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3376 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3377 This->StateBlock->streamIsUP = TRUE;
3378 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3379 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3381 /*stream zero settings set to null at end */
3382 This->StateBlock->stream_source[0] = NULL;
3383 This->StateBlock->stream_stride[0] = 0;
3384 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3386 return D3D_OK;
3388 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3389 ICOM_THIS(IDirect3DDevice8Impl,iface);
3390 FIXME("(%p) : stub\n", This); return D3D_OK;
3392 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3393 ICOM_THIS(IDirect3DDevice8Impl,iface);
3394 IDirect3DVertexShaderImpl* object;
3395 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3396 HRESULT res;
3397 UINT i;
3399 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3400 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3401 return D3DERR_INVALIDCALL;
3403 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3404 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3405 return D3DERR_OUTOFVIDEOMEMORY;
3408 /** Create the Vertex Shader */
3409 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3410 /** TODO: check FAILED(res) */
3412 /** Create and Bind the Vertex Shader Declaration */
3413 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3414 /** TODO: check FAILED(res) */
3416 VertexShaders[i] = object;
3417 VertexShaderDeclarations[i] = attached_decl;
3418 *pHandle = VS_HIGHESTFIXEDFXF + i;
3419 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3421 return D3D_OK;
3423 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3424 ICOM_THIS(IDirect3DDevice8Impl,iface);
3426 This->UpdateStateBlock->VertexShader = Handle;
3427 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3428 This->UpdateStateBlock->Set.vertexShader = TRUE;
3430 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3431 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3432 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3433 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3434 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3435 } else { /* use a fvf, so desactivate the vshader decl */
3436 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3437 This->UpdateStateBlock->vertexShaderDecl = NULL;
3438 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3439 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3441 /* Handle recording of state blocks */
3442 if (This->isRecordingState) {
3443 TRACE("Recording... not performing anything\n");
3444 return D3D_OK;
3447 * TODO: merge HAL shaders context switching from prototype
3449 return D3D_OK;
3451 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3452 ICOM_THIS(IDirect3DDevice8Impl,iface);
3453 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3454 *pHandle = This->StateBlock->VertexShader;
3455 return D3D_OK;
3458 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3459 ICOM_THIS(IDirect3DDevice8Impl,iface);
3460 IDirect3DVertexShaderImpl* object;
3461 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3463 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3464 return D3DERR_INVALIDCALL;
3468 * Delete Vertex Shader
3470 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3471 if (NULL == object) {
3472 return D3DERR_INVALIDCALL;
3474 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3475 /* TODO: check validity of object */
3476 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3477 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3478 HeapFree(GetProcessHeap(), 0, (void *)object);
3479 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3482 * Delete Vertex Shader Declaration
3484 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3485 if (NULL == attached_decl) {
3486 return D3DERR_INVALIDCALL;
3488 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3489 /* TODO: check validity of object */
3490 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3491 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3492 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3494 return D3D_OK;
3497 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3498 ICOM_THIS(IDirect3DDevice8Impl,iface);
3500 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3501 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3502 return D3DERR_INVALIDCALL;
3504 if (NULL == pConstantData) {
3505 return D3DERR_INVALIDCALL;
3507 if (ConstantCount > 1) {
3508 FLOAT* f = (FLOAT*)pConstantData;
3509 UINT i;
3510 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3511 for (i = 0; i < ConstantCount; ++i) {
3512 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3513 f += 4;
3515 } else {
3516 FLOAT* f = (FLOAT*) pConstantData;
3517 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3519 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3520 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3521 return D3D_OK;
3523 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3524 ICOM_THIS(IDirect3DDevice8Impl,iface);
3526 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3527 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3528 return D3DERR_INVALIDCALL;
3530 if (NULL == pConstantData) {
3531 return D3DERR_INVALIDCALL;
3533 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3534 return D3D_OK;
3536 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3537 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3538 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3540 attached_decl = VERTEX_SHADER_DECL(Handle);
3541 if (NULL == attached_decl) {
3542 return D3DERR_INVALIDCALL;
3544 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3546 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3547 /*ICOM_THIS(IDirect3DDevice8Impl,iface);*/
3548 IDirect3DVertexShaderImpl* object;
3550 object = VERTEX_SHADER(Handle);
3551 if (NULL == object) {
3552 return D3DERR_INVALIDCALL;
3554 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3557 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3558 ICOM_THIS(IDirect3DDevice8Impl,iface);
3559 IDirect3DIndexBuffer8 *oldIdxs;
3561 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3562 oldIdxs = This->StateBlock->pIndexData;
3564 This->UpdateStateBlock->Changed.Indices = TRUE;
3565 This->UpdateStateBlock->Set.Indices = TRUE;
3566 This->UpdateStateBlock->pIndexData = pIndexData;
3567 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3569 /* Handle recording of state blocks */
3570 if (This->isRecordingState) {
3571 TRACE("Recording... not performing anything\n");
3572 return D3D_OK;
3575 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
3576 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
3577 return D3D_OK;
3579 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3580 ICOM_THIS(IDirect3DDevice8Impl,iface);
3581 FIXME("(%p) : stub\n", This);
3583 *ppIndexData = This->StateBlock->pIndexData;
3584 /* up ref count on ppindexdata */
3585 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3586 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3588 return D3D_OK;
3590 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3591 ICOM_THIS(IDirect3DDevice8Impl,iface);
3592 IDirect3DPixelShaderImpl* object;
3593 HRESULT res;
3594 UINT i;
3596 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3597 if (NULL == pFunction || NULL == pHandle) {
3598 return D3DERR_INVALIDCALL;
3600 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3601 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3602 return D3DERR_OUTOFVIDEOMEMORY;
3605 /** Create the Pixel Shader */
3606 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3607 if (SUCCEEDED(res)) {
3608 PixelShaders[i] = object;
3609 *pHandle = VS_HIGHESTFIXEDFXF + i;
3610 return D3D_OK;
3612 *pHandle = 0xFFFFFFFF;
3613 return res;
3615 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3616 ICOM_THIS(IDirect3DDevice8Impl,iface);
3618 This->UpdateStateBlock->PixelShader = Handle;
3619 This->UpdateStateBlock->Changed.pixelShader = TRUE;
3620 This->UpdateStateBlock->Set.pixelShader = TRUE;
3622 /* Handle recording of state blocks */
3623 if (This->isRecordingState) {
3624 TRACE_(d3d_shader)("Recording... not performing anything\n");
3625 return D3D_OK;
3628 /* FIXME: Quieten when not being used */
3629 if (Handle != 0) {
3630 FIXME_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3631 } else {
3632 TRACE_(d3d_shader)("(%p) : stub %ld\n", This, Handle);
3635 return D3D_OK;
3637 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3638 ICOM_THIS(IDirect3DDevice8Impl,iface);
3639 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
3640 *pHandle = This->StateBlock->PixelShader;
3641 return D3D_OK;
3644 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3645 ICOM_THIS(IDirect3DDevice8Impl,iface);
3646 IDirect3DPixelShaderImpl* object;
3648 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3649 return D3DERR_INVALIDCALL;
3651 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
3652 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
3653 /* TODO: check validity of object before free */
3654 if (NULL != object->function) HeapFree(GetProcessHeap(), 0, (void *)object->function);
3655 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3656 HeapFree(GetProcessHeap(), 0, (void *)object);
3657 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3659 return D3D_OK;
3662 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3663 ICOM_THIS(IDirect3DDevice8Impl,iface);
3665 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
3666 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
3667 return D3DERR_INVALIDCALL;
3669 if (NULL == pConstantData) {
3670 return D3DERR_INVALIDCALL;
3672 if (ConstantCount > 1) {
3673 FLOAT* f = (FLOAT*)pConstantData;
3674 UINT i;
3675 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3676 for (i = 0; i < ConstantCount; ++i) {
3677 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3678 f += 4;
3680 } else {
3681 FLOAT* f = (FLOAT*) pConstantData;
3682 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3684 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
3685 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3686 return D3D_OK;
3688 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3689 ICOM_THIS(IDirect3DDevice8Impl,iface);
3691 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3692 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
3693 return D3DERR_INVALIDCALL;
3695 if (NULL == pConstantData) {
3696 return D3DERR_INVALIDCALL;
3698 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3699 return D3D_OK;
3701 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3702 IDirect3DPixelShaderImpl* object;
3704 object = PIXEL_SHADER(Handle);
3705 if (NULL == object) {
3706 return D3DERR_INVALIDCALL;
3708 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3710 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
3711 ICOM_THIS(IDirect3DDevice8Impl,iface);
3712 FIXME("(%p) : stub\n", This); return D3D_OK;
3714 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
3715 ICOM_THIS(IDirect3DDevice8Impl,iface);
3716 FIXME("(%p) : stub\n", This); return D3D_OK;
3718 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
3719 ICOM_THIS(IDirect3DDevice8Impl,iface);
3720 FIXME("(%p) : stub\n", This); return D3D_OK;
3723 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
3724 IDirect3DVertexBuffer8 *oldSrc;
3725 ICOM_THIS(IDirect3DDevice8Impl,iface);
3727 oldSrc = This->StateBlock->stream_source[StreamNumber];
3728 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
3730 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
3731 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
3732 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
3733 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
3735 /* Handle recording of state blocks */
3736 if (This->isRecordingState) {
3737 TRACE("Recording... not performing anything\n");
3738 return D3D_OK;
3741 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
3742 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
3743 return D3D_OK;
3745 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
3746 ICOM_THIS(IDirect3DDevice8Impl,iface);
3747 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
3748 *pStream = This->StateBlock->stream_source[StreamNumber];
3749 *pStride = This->StateBlock->stream_stride[StreamNumber];
3750 IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
3751 return D3D_OK;
3755 ICOM_VTABLE(IDirect3DDevice8) Direct3DDevice8_Vtbl =
3757 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
3758 IDirect3DDevice8Impl_QueryInterface,
3759 IDirect3DDevice8Impl_AddRef,
3760 IDirect3DDevice8Impl_Release,
3761 IDirect3DDevice8Impl_TestCooperativeLevel,
3762 IDirect3DDevice8Impl_GetAvailableTextureMem,
3763 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
3764 IDirect3DDevice8Impl_GetDirect3D,
3765 IDirect3DDevice8Impl_GetDeviceCaps,
3766 IDirect3DDevice8Impl_GetDisplayMode,
3767 IDirect3DDevice8Impl_GetCreationParameters,
3768 IDirect3DDevice8Impl_SetCursorProperties,
3769 IDirect3DDevice8Impl_SetCursorPosition,
3770 IDirect3DDevice8Impl_ShowCursor,
3771 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
3772 IDirect3DDevice8Impl_Reset,
3773 IDirect3DDevice8Impl_Present,
3774 IDirect3DDevice8Impl_GetBackBuffer,
3775 IDirect3DDevice8Impl_GetRasterStatus,
3776 IDirect3DDevice8Impl_SetGammaRamp,
3777 IDirect3DDevice8Impl_GetGammaRamp,
3778 IDirect3DDevice8Impl_CreateTexture,
3779 IDirect3DDevice8Impl_CreateVolumeTexture,
3780 IDirect3DDevice8Impl_CreateCubeTexture,
3781 IDirect3DDevice8Impl_CreateVertexBuffer,
3782 IDirect3DDevice8Impl_CreateIndexBuffer,
3783 IDirect3DDevice8Impl_CreateRenderTarget,
3784 IDirect3DDevice8Impl_CreateDepthStencilSurface,
3785 IDirect3DDevice8Impl_CreateImageSurface,
3786 IDirect3DDevice8Impl_CopyRects,
3787 IDirect3DDevice8Impl_UpdateTexture,
3788 IDirect3DDevice8Impl_GetFrontBuffer,
3789 IDirect3DDevice8Impl_SetRenderTarget,
3790 IDirect3DDevice8Impl_GetRenderTarget,
3791 IDirect3DDevice8Impl_GetDepthStencilSurface,
3792 IDirect3DDevice8Impl_BeginScene,
3793 IDirect3DDevice8Impl_EndScene,
3794 IDirect3DDevice8Impl_Clear,
3795 IDirect3DDevice8Impl_SetTransform,
3796 IDirect3DDevice8Impl_GetTransform,
3797 IDirect3DDevice8Impl_MultiplyTransform,
3798 IDirect3DDevice8Impl_SetViewport,
3799 IDirect3DDevice8Impl_GetViewport,
3800 IDirect3DDevice8Impl_SetMaterial,
3801 IDirect3DDevice8Impl_GetMaterial,
3802 IDirect3DDevice8Impl_SetLight,
3803 IDirect3DDevice8Impl_GetLight,
3804 IDirect3DDevice8Impl_LightEnable,
3805 IDirect3DDevice8Impl_GetLightEnable,
3806 IDirect3DDevice8Impl_SetClipPlane,
3807 IDirect3DDevice8Impl_GetClipPlane,
3808 IDirect3DDevice8Impl_SetRenderState,
3809 IDirect3DDevice8Impl_GetRenderState,
3810 IDirect3DDevice8Impl_BeginStateBlock,
3811 IDirect3DDevice8Impl_EndStateBlock,
3812 IDirect3DDevice8Impl_ApplyStateBlock,
3813 IDirect3DDevice8Impl_CaptureStateBlock,
3814 IDirect3DDevice8Impl_DeleteStateBlock,
3815 IDirect3DDevice8Impl_CreateStateBlock,
3816 IDirect3DDevice8Impl_SetClipStatus,
3817 IDirect3DDevice8Impl_GetClipStatus,
3818 IDirect3DDevice8Impl_GetTexture,
3819 IDirect3DDevice8Impl_SetTexture,
3820 IDirect3DDevice8Impl_GetTextureStageState,
3821 IDirect3DDevice8Impl_SetTextureStageState,
3822 IDirect3DDevice8Impl_ValidateDevice,
3823 IDirect3DDevice8Impl_GetInfo,
3824 IDirect3DDevice8Impl_SetPaletteEntries,
3825 IDirect3DDevice8Impl_GetPaletteEntries,
3826 IDirect3DDevice8Impl_SetCurrentTexturePalette,
3827 IDirect3DDevice8Impl_GetCurrentTexturePalette,
3828 IDirect3DDevice8Impl_DrawPrimitive,
3829 IDirect3DDevice8Impl_DrawIndexedPrimitive,
3830 IDirect3DDevice8Impl_DrawPrimitiveUP,
3831 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
3832 IDirect3DDevice8Impl_ProcessVertices,
3833 IDirect3DDevice8Impl_CreateVertexShader,
3834 IDirect3DDevice8Impl_SetVertexShader,
3835 IDirect3DDevice8Impl_GetVertexShader,
3836 IDirect3DDevice8Impl_DeleteVertexShader,
3837 IDirect3DDevice8Impl_SetVertexShaderConstant,
3838 IDirect3DDevice8Impl_GetVertexShaderConstant,
3839 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
3840 IDirect3DDevice8Impl_GetVertexShaderFunction,
3841 IDirect3DDevice8Impl_SetStreamSource,
3842 IDirect3DDevice8Impl_GetStreamSource,
3843 IDirect3DDevice8Impl_SetIndices,
3844 IDirect3DDevice8Impl_GetIndices,
3845 IDirect3DDevice8Impl_CreatePixelShader,
3846 IDirect3DDevice8Impl_SetPixelShader,
3847 IDirect3DDevice8Impl_GetPixelShader,
3848 IDirect3DDevice8Impl_DeletePixelShader,
3849 IDirect3DDevice8Impl_SetPixelShaderConstant,
3850 IDirect3DDevice8Impl_GetPixelShaderConstant,
3851 IDirect3DDevice8Impl_GetPixelShaderFunction,
3852 IDirect3DDevice8Impl_DrawRectPatch,
3853 IDirect3DDevice8Impl_DrawTriPatch,
3854 IDirect3DDevice8Impl_DeletePatch
3857 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
3859 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
3860 ICOM_THIS(IDirect3DDevice8Impl,iface);
3862 ENTER_GL();
3864 #if 0
3865 if (This->glCtx != This->render_ctx) {
3866 glXDestroyContext(This->display, This->render_ctx);
3867 This->render_ctx = This->glCtx;
3869 #endif
3870 if (This->win != This->drawable) {
3871 glXDestroyPbuffer(This->display, This->drawable);
3872 This->drawable = This->win;
3875 LEAVE_GL();
3877 #endif
3878 return D3D_OK;
3881 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
3882 IDirect3DSurface8* RenderSurface,
3883 IDirect3DSurface8* StencilSurface) {
3885 HRESULT ret = D3DERR_INVALIDCALL;
3887 * Currently only active for GLX >= 1.3
3888 * for others versions we'll have to use GLXPixmaps
3890 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
3891 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
3892 * so only check OpenGL version
3894 #if defined(GL_VERSION_1_3)
3895 GLXFBConfig* cfgs = NULL;
3896 int nCfgs = 0;
3897 int attribs[256];
3898 int nAttribs = 0;
3899 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
3900 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
3901 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
3902 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
3903 IDirect3DSurface8Impl* tmp;
3905 ICOM_THIS(IDirect3DDevice8Impl,iface);
3907 #define PUSH1(att) attribs[nAttribs++] = (att);
3908 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
3910 PUSH2(GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT | GLX_WINDOW | GLX_PBUFFER_BIT);
3911 PUSH2(GLX_X_RENDERABLE, TRUE);
3912 PUSH2(GLX_DOUBLEBUFFER, TRUE);
3914 switch (BackBufferFormat) {
3915 /* color buffer */
3916 case D3DFMT_P8:
3917 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
3918 PUSH2(GLX_BUFFER_SIZE, 8);
3919 PUSH2(GLX_DOUBLEBUFFER, TRUE);
3920 break;
3922 case D3DFMT_R3G3B2:
3923 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
3924 PUSH2(GLX_RED_SIZE, 3);
3925 PUSH2(GLX_GREEN_SIZE, 3);
3926 PUSH2(GLX_BLUE_SIZE, 2);
3927 break;
3929 case D3DFMT_A1R5G5B5:
3930 PUSH2(GLX_ALPHA_SIZE, 1);
3931 case D3DFMT_X1R5G5B5:
3932 PUSH2(GLX_RED_SIZE, 5);
3933 PUSH2(GLX_GREEN_SIZE, 5);
3934 PUSH2(GLX_BLUE_SIZE, 5);
3935 break;
3937 case D3DFMT_R5G6B5:
3938 PUSH2(GLX_RED_SIZE, 5);
3939 PUSH2(GLX_GREEN_SIZE, 6);
3940 PUSH2(GLX_BLUE_SIZE, 5);
3941 break;
3943 case D3DFMT_A4R4G4B4:
3944 PUSH2(GLX_ALPHA_SIZE, 4);
3945 case D3DFMT_X4R4G4B4:
3946 PUSH2(GLX_RED_SIZE, 4);
3947 PUSH2(GLX_GREEN_SIZE, 4);
3948 PUSH2(GLX_BLUE_SIZE, 4);
3949 break;
3951 case D3DFMT_A8R8G8B8:
3952 PUSH2(GLX_ALPHA_SIZE, 8);
3953 case D3DFMT_R8G8B8:
3954 case D3DFMT_X8R8G8B8:
3955 PUSH2(GLX_RED_SIZE, 8);
3956 PUSH2(GLX_GREEN_SIZE, 8);
3957 PUSH2(GLX_BLUE_SIZE, 8);
3958 break;
3960 default:
3961 break;
3964 switch (StencilBufferFormat) {
3965 case D3DFMT_D16_LOCKABLE:
3966 case D3DFMT_D16:
3967 PUSH2(GLX_DEPTH_SIZE, 16);
3968 break;
3970 case D3DFMT_D15S1:
3971 PUSH2(GLX_DEPTH_SIZE, 15);
3972 break;
3974 case D3DFMT_D24X8:
3975 PUSH2(GLX_DEPTH_SIZE, 24);
3976 break;
3978 case D3DFMT_D24X4S4:
3979 PUSH2(GLX_DEPTH_SIZE, 24);
3980 PUSH2(GLX_STENCIL_SIZE, 4);
3981 break;
3983 case D3DFMT_D24S8:
3984 PUSH2(GLX_DEPTH_SIZE, 24);
3985 PUSH2(GLX_STENCIL_SIZE, 8);
3986 break;
3988 case D3DFMT_D32:
3989 PUSH2(GLX_DEPTH_SIZE, 32);
3990 break;
3992 default:
3993 break;
3996 PUSH1(None);
3998 ENTER_GL();
4000 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4001 if (NULL != cfgs) {
4002 #if 0
4003 int i;
4004 for (i = 0; i < nCfgs; ++i) {
4005 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4007 #endif
4009 if (NULL != This->renderTarget) {
4010 GLenum prev_read;
4011 glFlush();
4012 vcheckGLcall("glFlush");
4014 #if 0
4015 /** very very usefull debug code */
4016 glXSwapBuffers(This->display, This->drawable);
4017 printf("Hit Enter to get next frame ...\n");
4018 getchar();
4019 #endif
4021 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4022 vcheckGLcall("glIntegerv");
4023 glReadBuffer(GL_BACK);
4024 vcheckGLcall("glReadBuffer");
4026 long j;
4027 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4028 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4029 glReadPixels(0,
4030 This->renderTarget->myDesc.Height - j - 1,
4031 This->renderTarget->myDesc.Width,
4033 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4034 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4035 This->renderTarget->allocatedMemory + j * pitch);
4036 vcheckGLcall("glReadPixels");
4039 glReadBuffer(prev_read);
4040 vcheckGLcall("glReadBuffer");
4043 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4044 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4045 nAttribs = 0;
4046 PUSH2(GLX_PBUFFER_WIDTH, Width);
4047 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4048 PUSH1(None);
4049 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4051 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4052 if (NULL == This->render_ctx) {
4053 ERR("cannot create glxContext\n");
4056 glFlush();
4057 glXSwapBuffers(This->display, This->drawable);
4058 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4059 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4061 checkGLcall("glXMakeContextCurrent");
4064 tmp = This->renderTarget;
4065 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4066 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4067 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4069 tmp = This->stencilBufferTarget;
4070 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4071 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4072 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4074 ret = D3D_OK;
4076 } else {
4077 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4080 #undef PUSH1
4081 #undef PUSH2
4083 LEAVE_GL();
4085 #endif
4087 return ret;