Assorted spelling fixes.
[wine/dibdrv.git] / dlls / d3d8 / device.c
blob4f8e5d09e8a1bfef4799dab7f907bb92360eac88
1 /*
2 * IDirect3DDevice8 implementation
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2004 Christian Costa
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
24 #include <math.h>
25 #include <stdarg.h>
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winbase.h"
31 #include "winuser.h"
32 #include "wingdi.h"
33 #include "wine/debug.h"
35 /** define GL_GLEXT_PROTOTYPES for having extensions prototypes defined */
36 /*#define GL_GLEXT_PROTOTYPES*/
37 /*#undef GLX_GLXEXT_LEGACY*/
38 #include "d3d8_private.h"
40 /** currently desactiving 1_4 support as mesa doesn't implement all 1_4 support while defining it */
41 #undef GL_VERSION_1_4
43 /* Uncomment the next line to get extra traces, important but impact speed */
44 /* #define EXTRA_TRACES */
46 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
47 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
48 WINE_DECLARE_DEBUG_CHANNEL(d3d_fps);
50 IDirect3DVertexShaderImpl* VertexShaders[64];
51 IDirect3DVertexShaderDeclarationImpl* VertexShaderDeclarations[64];
52 IDirect3DPixelShaderImpl* PixelShaders[64];
54 /* Debugging aids: */
55 #ifdef FRAME_DEBUGGING
56 BOOL isOn = FALSE;
57 BOOL isDumpingFrames = FALSE;
58 LONG primCounter = 0;
59 #endif
62 * Utility functions or macros
64 #define conv_mat(mat,gl_mat) \
65 do { \
66 TRACE("%f %f %f %f\n", (mat)->u.s._11, (mat)->u.s._12, (mat)->u.s._13, (mat)->u.s._14); \
67 TRACE("%f %f %f %f\n", (mat)->u.s._21, (mat)->u.s._22, (mat)->u.s._23, (mat)->u.s._24); \
68 TRACE("%f %f %f %f\n", (mat)->u.s._31, (mat)->u.s._32, (mat)->u.s._33, (mat)->u.s._34); \
69 TRACE("%f %f %f %f\n", (mat)->u.s._41, (mat)->u.s._42, (mat)->u.s._43, (mat)->u.s._44); \
70 memcpy(gl_mat, (mat), 16 * sizeof(float)); \
71 } while (0)
73 /* Apply the current values to the specified texture stage */
74 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage, DWORD Flags) {
75 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
76 int i = 0;
77 float col[4];
78 BOOL changeTexture = TRUE;
80 TRACE("-----------------------> Updating the texture at stage %ld to have new texture state information\n", Stage);
81 for (i = 1; i < HIGHEST_TEXTURE_STATE; i++) {
83 BOOL skip = FALSE;
85 switch (i) {
86 /* Performance: For texture states where multiples effect the outcome, only bother
87 applying the last one as it will pick up all the other values */
88 case D3DTSS_COLORARG0: /* Will be picked up when setting color op */
89 case D3DTSS_COLORARG1: /* Will be picked up when setting color op */
90 case D3DTSS_COLORARG2: /* Will be picked up when setting color op */
91 case D3DTSS_ALPHAARG0: /* Will be picked up when setting alpha op */
92 case D3DTSS_ALPHAARG1: /* Will be picked up when setting alpha op */
93 case D3DTSS_ALPHAARG2: /* Will be picked up when setting alpha op */
94 skip = TRUE;
95 break;
97 /* Performance: If the texture states only impact settings for the texture unit
98 (compared to the texture object) then there is no need to reapply them. The
99 only time they need applying is the first time, since we cheat and put the
100 values into the stateblock without applying.
101 Per-texture unit: texture function (eg. combine), ops and args
102 texture env color
103 texture generation settings
104 Note: Due to some special conditions there may be a need to do particular ones
105 of these, which is what the Flags allows */
106 case D3DTSS_COLOROP:
107 case D3DTSS_TEXCOORDINDEX:
108 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
109 break;
111 case D3DTSS_ALPHAOP:
112 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
113 break;
115 default:
116 skip = FALSE;
119 if (skip == FALSE) {
120 /* Performance: Only change to this texture if we have to */
121 if (changeTexture) {
122 /* Make appropriate texture active */
123 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
124 #if defined(GL_VERSION_1_3)
125 glActiveTexture(GL_TEXTURE0 + Stage);
126 checkGLcall("glActiveTexture");
127 #else
128 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
129 checkGLcall("glActiveTextureARB");
130 #endif
131 } else if (Stage > 0) {
132 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
134 changeTexture = FALSE;
137 /* Now apply the change */
138 IDirect3DDevice8Impl_SetTextureStageState(iface, Stage, i, This->StateBlock->texture_state[Stage][i]);
142 /* Note the D3DRS value applies to all textures, but GL has one
143 * per texture, so apply it now ready to be used!
145 D3DCOLORTOGLFLOAT4(This->StateBlock->renderstate[D3DRS_TEXTUREFACTOR], col);
146 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
147 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
149 TRACE("-----------------------> Updated the texture at stage %ld to have new texture state information\n", Stage);
152 /* Convert the D3DLIGHT8 properties into equivalent gl lights */
153 void setup_light(LPDIRECT3DDEVICE8 iface, LONG Index, PLIGHTINFOEL *lightInfo) {
155 float quad_att;
156 float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
157 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
159 /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
160 glMatrixMode(GL_MODELVIEW);
161 glPushMatrix();
162 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
164 /* Diffuse: */
165 colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
166 colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
167 colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
168 colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
169 glLightfv(GL_LIGHT0+Index, GL_DIFFUSE, colRGBA);
170 checkGLcall("glLightfv");
172 /* Specular */
173 colRGBA[0] = lightInfo->OriginalParms.Specular.r;
174 colRGBA[1] = lightInfo->OriginalParms.Specular.g;
175 colRGBA[2] = lightInfo->OriginalParms.Specular.b;
176 colRGBA[3] = lightInfo->OriginalParms.Specular.a;
177 glLightfv(GL_LIGHT0+Index, GL_SPECULAR, colRGBA);
178 checkGLcall("glLightfv");
180 /* Ambient */
181 colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
182 colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
183 colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
184 colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
185 glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
186 checkGLcall("glLightfv");
188 /* Attenuation - Are these right? guessing... */
189 glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
190 checkGLcall("glLightf");
191 glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
192 checkGLcall("glLightf");
194 quad_att = 1.4/(lightInfo->OriginalParms.Range*lightInfo->OriginalParms.Range);
195 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
196 glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
197 checkGLcall("glLightf");
199 switch (lightInfo->OriginalParms.Type) {
200 case D3DLIGHT_POINT:
201 /* Position */
202 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
203 checkGLcall("glLightfv");
204 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
205 checkGLcall("glLightf");
206 /* FIXME: Range */
207 break;
209 case D3DLIGHT_SPOT:
210 /* Position */
211 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
212 checkGLcall("glLightfv");
213 /* Direction */
214 glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
215 checkGLcall("glLightfv");
216 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
217 checkGLcall("glLightf");
218 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
219 checkGLcall("glLightf");
220 /* FIXME: Range */
221 break;
223 case D3DLIGHT_DIRECTIONAL:
224 /* Direction */
225 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
226 checkGLcall("glLightfv");
227 glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
228 checkGLcall("glLightf");
229 glLightf(GL_LIGHT0+Index, GL_SPOT_EXPONENT, 0.0f);
230 checkGLcall("glLightf");
231 break;
233 default:
234 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
237 /* Restore the modelview matrix */
238 glPopMatrix();
241 /* Setup this textures matrix */
242 static void set_texture_matrix(const float *smat, DWORD flags)
244 float mat[16];
246 glMatrixMode(GL_TEXTURE);
248 if (flags == D3DTTFF_DISABLE) {
249 glLoadIdentity();
250 checkGLcall("glLoadIdentity()");
251 return;
254 if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
255 ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
256 checkGLcall("glLoadIdentity()");
257 return;
260 memcpy(mat, smat, 16*sizeof(float));
262 switch (flags & ~D3DTTFF_PROJECTED) {
263 case D3DTTFF_COUNT1: mat[1] = mat[5] = mat[9] = mat[13] = 0;
264 case D3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
265 default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
268 if (flags & D3DTTFF_PROJECTED) switch (flags & ~D3DTTFF_PROJECTED) {
269 case D3DTTFF_COUNT2:
270 mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
271 mat[1] = mat[5] = mat[9] = mat[13] = 0;
272 break;
273 case D3DTTFF_COUNT3:
274 mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
275 mat[2] = mat[6] = mat[10] = mat[14] = 0;
276 break;
278 glLoadMatrixf(mat);
279 checkGLcall("glLoadMatrixf(mat)");
282 /* IDirect3D IUnknown parts follow: */
283 HRESULT WINAPI IDirect3DDevice8Impl_QueryInterface(LPDIRECT3DDEVICE8 iface,REFIID riid,LPVOID *ppobj)
285 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
287 if (IsEqualGUID(riid, &IID_IUnknown)
288 || IsEqualGUID(riid, &IID_IDirect3DDevice8)) {
289 IDirect3DDevice8Impl_AddRef(iface);
290 *ppobj = This;
291 return D3D_OK;
294 WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
295 return E_NOINTERFACE;
298 ULONG WINAPI IDirect3DDevice8Impl_AddRef(LPDIRECT3DDEVICE8 iface) {
299 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
300 ULONG ref = InterlockedIncrement(&This->ref);
302 TRACE("(%p) : AddRef from %ld\n", This, ref - 1);
304 return ref;
307 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
308 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
309 ULONG ref = InterlockedDecrement(&This->ref);
311 TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
313 if (ref == 0) {
314 IDirect3DDevice8Impl_CleanRender(iface);
315 IDirect3D8_Release((LPDIRECT3D8) This->direct3d8);
316 IWineD3DDevice_Release(This->WineD3DDevice);
317 HeapFree(GetProcessHeap(), 0, This);
319 return ref;
322 /* IDirect3DDevice Interface follow: */
323 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
324 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
325 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
326 return D3D_OK;
329 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
330 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
331 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
333 * pretend we have 32MB of any type of memory queried.
335 return (1024*1024*32);
338 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
339 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
340 FIXME("(%p) : stub\n", This);
341 return D3D_OK;
343 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
344 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
345 TRACE("(%p) : returning %p\n", This, This->direct3d8);
347 /* Inc ref count */
348 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
350 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
351 return D3D_OK;
353 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
354 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
355 FIXME("(%p) : stub, calling idirect3d for now\n", This);
356 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
357 return D3D_OK;
359 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
361 HDC hdc;
362 int bpp = 0;
364 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
365 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
366 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
367 pMode->RefreshRate = 85; /*FIXME: How to identify? */
369 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
370 bpp = GetDeviceCaps(hdc, BITSPIXEL);
371 DeleteDC(hdc);
373 switch (bpp) {
374 case 8: pMode->Format = D3DFMT_R8G8B8; break;
375 case 16: pMode->Format = D3DFMT_R5G6B5; break;
376 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
377 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
378 default:
379 FIXME("Unrecognized display mode format\n");
380 pMode->Format = D3DFMT_UNKNOWN;
383 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
384 pMode->Format, debug_d3dformat(pMode->Format));
385 return D3D_OK;
387 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
388 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
389 TRACE("(%p) copying to %p\n", This, pParameters);
390 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
391 return D3D_OK;
393 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
394 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
395 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
396 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
398 if (D3DFMT_A8R8G8B8 != pSur->myDesc.Format) {
399 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
400 return D3DERR_INVALIDCALL;
402 if (32 != pSur->myDesc.Height || 32 != pSur->myDesc.Width) {
403 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
404 return D3DERR_INVALIDCALL;
407 This->xHotSpot = XHotSpot;
408 This->yHotSpot = YHotSpot;
409 return D3D_OK;
411 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
412 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
413 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
414 This->xScreenSpace = XScreenSpace;
415 This->yScreenSpace = YScreenSpace;
416 return;
418 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
419 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
420 TRACE("(%p) : visible(%d)\n", This, bShow);
421 This->bCursorVisible = bShow;
422 return D3D_OK;
424 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
425 IDirect3DSwapChain8Impl* object;
426 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
427 FIXME("(%p) : stub\n", This);
429 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
430 if (NULL == object) {
431 return D3DERR_OUTOFVIDEOMEMORY;
433 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
434 object->ref = 1;
436 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
437 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
438 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
440 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
441 (pPresentationParameters->BackBufferHeight == 0))) {
442 RECT Rect;
444 GetClientRect(This->win_handle, &Rect);
446 if (pPresentationParameters->BackBufferWidth == 0) {
447 pPresentationParameters->BackBufferWidth = Rect.right;
448 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
450 if (pPresentationParameters->BackBufferHeight == 0) {
451 pPresentationParameters->BackBufferHeight = Rect.bottom;
452 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
456 /* Save the presentation parms now filled in correctly */
457 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
459 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
460 pPresentationParameters->BackBufferWidth,
461 pPresentationParameters->BackBufferHeight,
462 pPresentationParameters->BackBufferFormat,
463 pPresentationParameters->MultiSampleType,
464 TRUE,
465 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
467 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
468 pPresentationParameters->BackBufferWidth,
469 pPresentationParameters->BackBufferHeight,
470 pPresentationParameters->BackBufferFormat,
471 pPresentationParameters->MultiSampleType,
472 TRUE,
473 (LPDIRECT3DSURFACE8*) &object->backBuffer);
475 if (pPresentationParameters->EnableAutoDepthStencil) {
476 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
477 pPresentationParameters->BackBufferWidth,
478 pPresentationParameters->BackBufferHeight,
479 pPresentationParameters->AutoDepthStencilFormat,
480 D3DMULTISAMPLE_NONE,
481 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
482 } else {
483 object->depthStencilBuffer = NULL;
486 *pSwapChain = (IDirect3DSwapChain8*) object;
487 return D3D_OK;
489 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
490 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
491 FIXME("(%p) : stub\n", This);
492 return D3D_OK;
494 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface,
495 CONST RECT* pSourceRect, CONST RECT* pDestRect,
496 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
497 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
498 TRACE("(%p) : complete stub!\n", This);
500 ENTER_GL();
502 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
505 glXSwapBuffers(This->display, This->drawable);
506 /* Don't call checkGLcall, as glGetError is not applicable here */
507 TRACE("glXSwapBuffers called, Starting new frame\n");
509 /* FPS support */
510 if (TRACE_ON(d3d_fps))
512 static long prev_time, frames;
514 DWORD time = GetTickCount();
515 frames++;
516 /* every 1.5 seconds */
517 if (time - prev_time > 1500) {
518 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
519 prev_time = time;
520 frames = 0;
524 #if defined(FRAME_DEBUGGING)
526 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
527 if (!isOn) {
528 isOn = TRUE;
529 FIXME("Enabling D3D Trace\n");
530 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
531 #if defined(SHOW_FRAME_MAKEUP)
532 FIXME("Singe Frame snapshots Starting\n");
533 isDumpingFrames = TRUE;
534 glClear(GL_COLOR_BUFFER_BIT);
535 #endif
537 #if defined(SINGLE_FRAME_DEBUGGING)
538 } else {
539 #if defined(SHOW_FRAME_MAKEUP)
540 FIXME("Singe Frame snapshots Finishing\n");
541 isDumpingFrames = FALSE;
542 #endif
543 FIXME("Singe Frame trace complete\n");
544 DeleteFileA("C:\\D3DTRACE");
545 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
546 #endif
548 } else {
549 if (isOn) {
550 isOn = FALSE;
551 #if defined(SHOW_FRAME_MAKEUP)
552 FIXME("Singe Frame snapshots Finishing\n");
553 isDumpingFrames = FALSE;
554 #endif
555 FIXME("Disabling D3D Trace\n");
556 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
560 #endif
562 LEAVE_GL();
563 /* Although this is not strictly required, a simple demo showed this does occur
564 on (at least non-debug) d3d */
565 if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
566 IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
569 return D3D_OK;
571 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
572 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
573 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
574 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
576 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
577 FIXME("Only one backBuffer currently supported\n");
578 return D3DERR_INVALIDCALL;
581 /* Note inc ref on returned surface */
582 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
584 return D3D_OK;
586 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
587 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
588 FIXME("(%p) : stub\n", This);
589 return D3D_OK;
591 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
592 HDC hDC;
593 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
595 FIXME("(%p) : pRamp@%p\n", This, pRamp);
596 hDC = GetDC(This->win_handle);
597 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
598 ReleaseDC(This->win_handle, hDC);
599 return;
601 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
602 HDC hDC;
603 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
605 FIXME("(%p) : pRamp@%p\n", This, pRamp);
606 hDC = GetDC(This->win_handle);
607 GetDeviceGammaRamp(hDC, pRamp);
608 ReleaseDC(This->win_handle, hDC);
609 return;
611 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
612 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8** ppTexture) {
613 IDirect3DTexture8Impl *object;
614 unsigned int i;
615 UINT tmpW;
616 UINT tmpH;
618 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
620 /* Allocate the storage for the device */
621 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);
622 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
623 object->lpVtbl = &Direct3DTexture8_Vtbl;
624 object->Device = This;
625 object->ResourceType = D3DRTYPE_TEXTURE;
626 object->ref = 1;
627 object->width = Width;
628 object->height = Height;
629 object->levels = Levels;
630 object->usage = Usage;
631 object->format = Format;
633 /* Calculate levels for mip mapping */
634 if (Levels == 0) {
635 object->levels++;
636 tmpW = Width;
637 tmpH = Height;
638 while (tmpW > 1 && tmpH > 1) {
639 tmpW = max(1, tmpW / 2);
640 tmpH = max(1, tmpH / 2);
641 object->levels++;
643 TRACE("Calculated levels = %d\n", object->levels);
646 /* Generate all the surfaces */
647 tmpW = Width;
648 tmpH = Height;
649 for (i = 0; i < object->levels; i++)
651 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpH, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[i]);
652 object->surfaces[i]->Container = (IUnknown*) object;
653 object->surfaces[i]->myDesc.Usage = Usage;
654 object->surfaces[i]->myDesc.Pool = Pool;
655 /**
656 * As written in msdn in IDirect3DTexture8::LockRect
657 * Textures created in D3DPOOL_DEFAULT are not lockable.
659 if (D3DPOOL_DEFAULT == Pool) {
660 object->surfaces[i]->lockable = FALSE;
663 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[i], object->surfaces[i]->allocatedMemory);
664 tmpW = max(1, tmpW / 2);
665 tmpH = max(1, tmpH / 2);
668 *ppTexture = (LPDIRECT3DTEXTURE8) object;
669 TRACE("(%p) : Created texture %p\n", This, object);
670 return D3D_OK;
672 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
673 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
674 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
676 IDirect3DVolumeTexture8Impl *object;
677 unsigned int i;
678 UINT tmpW;
679 UINT tmpH;
680 UINT tmpD;
682 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
684 /* Allocate the storage for it */
685 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));
686 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
687 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
688 object->ResourceType = D3DRTYPE_VOLUMETEXTURE;
689 object->Device = This;
690 object->ref = 1;
692 object->width = Width;
693 object->height = Height;
694 object->depth = Depth;
695 object->levels = Levels;
696 object->usage = Usage;
697 object->format = Format;
699 /* Calculate levels for mip mapping */
700 if (Levels == 0) {
701 object->levels++;
702 tmpW = Width;
703 tmpH = Height;
704 tmpD = Depth;
705 while (tmpW > 1 && tmpH > 1 && tmpD > 1) {
706 tmpW = max(1, tmpW / 2);
707 tmpH = max(1, tmpH / 2);
708 tmpD = max(1, tmpD / 2);
709 object->levels++;
711 TRACE("Calculated levels = %d\n", object->levels);
714 /* Generate all the surfaces */
715 tmpW = Width;
716 tmpH = Height;
717 tmpD = Depth;
719 for (i = 0; i < object->levels; i++)
721 IDirect3DVolume8Impl* volume;
723 /* Create the volume - No entry point for this seperately?? */
724 volume = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolume8Impl));
725 object->volumes[i] = (IDirect3DVolume8Impl *) volume;
727 volume->lpVtbl = &Direct3DVolume8_Vtbl;
728 volume->Device = This;
729 volume->ResourceType = D3DRTYPE_VOLUME;
730 volume->Container = (IUnknown*) object;
731 volume->ref = 1;
733 volume->myDesc.Width = Width;
734 volume->myDesc.Height = Height;
735 volume->myDesc.Depth = Depth;
736 volume->myDesc.Format = Format;
737 volume->myDesc.Type = D3DRTYPE_VOLUME;
738 volume->myDesc.Pool = Pool;
739 volume->myDesc.Usage = Usage;
740 volume->bytesPerPixel = D3DFmtGetBpp(This, Format);
741 /* Note: Volume textures cannot be dxtn, hence no need to check here */
742 volume->myDesc.Size = (Width * volume->bytesPerPixel) * Height * Depth;
743 volume->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, volume->myDesc.Size);
745 volume->lockable = TRUE;
746 volume->locked = FALSE;
747 memset(&volume->lockedBox, 0, sizeof(D3DBOX));
748 volume->Dirty = FALSE;
749 IDirect3DVolume8Impl_CleanDirtyBox((LPDIRECT3DVOLUME8) volume);
751 TRACE("(%p) : Volume at w(%d) h(%d) d(%d) fmt(%u,%s) surf@%p, surfmem@%p, %d bytes\n",
752 This, Width, Height, Depth, Format, debug_d3dformat(Format),
753 volume, volume->allocatedMemory, volume->myDesc.Size);
755 tmpW = max(1, tmpW / 2);
756 tmpH = max(1, tmpH / 2);
757 tmpD = max(1, tmpD / 2);
760 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
761 TRACE("(%p) : Created volume texture %p\n", This, object);
762 return D3D_OK;
764 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
765 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
767 IDirect3DCubeTexture8Impl *object;
768 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
769 unsigned int i,j;
770 UINT tmpW;
772 /* Allocate the storage for it */
773 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));
774 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DCubeTexture8Impl));
775 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
776 object->ref = 1;
777 object->Device = This;
778 object->ResourceType = D3DRTYPE_CUBETEXTURE;
780 object->edgeLength = EdgeLength;
781 object->levels = Levels;
782 object->usage = Usage;
783 object->format = Format;
785 /* Calculate levels for mip mapping */
786 if (Levels == 0) {
787 object->levels++;
788 tmpW = EdgeLength;
789 while (tmpW > 1) {
790 tmpW = max(1, tmpW / 2);
791 object->levels++;
793 TRACE("Calculated levels = %d\n", object->levels);
796 /* Generate all the surfaces */
797 tmpW = EdgeLength;
798 for (i = 0; i < object->levels; i++) {
799 /* Create the 6 faces */
800 for (j = 0; j < 6; j++) {
801 IDirect3DDevice8Impl_CreateImageSurface(iface, tmpW, tmpW, Format, (LPDIRECT3DSURFACE8*) &object->surfaces[j][i]);
802 object->surfaces[j][i]->Container = (IUnknown*) object;
803 object->surfaces[j][i]->myDesc.Usage = Usage;
804 object->surfaces[j][i]->myDesc.Pool = Pool;
805 /**
806 * As written in msdn in IDirect3DCubeTexture8::LockRect
807 * Textures created in D3DPOOL_DEFAULT are not lockable.
809 if (D3DPOOL_DEFAULT == Pool) {
810 object->surfaces[j][i]->lockable = FALSE;
813 TRACE("Created surface level %d @ %p, memory at %p\n", i, object->surfaces[j][i], object->surfaces[j][i]->allocatedMemory);
815 tmpW = max(1, tmpW / 2);
818 TRACE("(%p) : Iface@%p\n", This, object);
819 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
820 return D3D_OK;
822 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
823 IDirect3DVertexBuffer8Impl *object;
825 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
827 /* Allocate the storage for the device */
828 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
829 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
830 object->Device = This;
831 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
832 object->ref = 1;
833 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
834 object->currentDesc.Usage = Usage;
835 object->currentDesc.Pool = Pool;
836 object->currentDesc.FVF = FVF;
837 object->currentDesc.Size = Size;
839 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
841 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
843 return D3D_OK;
845 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
846 IDirect3DIndexBuffer8Impl *object;
848 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
849 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
851 /* Allocate the storage for the device */
852 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
853 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
854 object->Device = This;
855 object->ref = 1;
856 object->ResourceType = D3DRTYPE_INDEXBUFFER;
858 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
859 object->currentDesc.Usage = Usage;
860 object->currentDesc.Pool = Pool;
861 object->currentDesc.Format = Format;
862 object->currentDesc.Size = Length;
864 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
866 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
868 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
870 return D3D_OK;
872 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
873 IDirect3DSurface8Impl *object;
874 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
876 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
877 if (NULL == object) {
878 *ppSurface = NULL;
879 return D3DERR_OUTOFVIDEOMEMORY;
881 *ppSurface = (LPDIRECT3DSURFACE8) object;
882 object->lpVtbl = &Direct3DSurface8_Vtbl;
883 object->Device = This;
884 object->ResourceType = D3DRTYPE_SURFACE;
885 object->Container = (IUnknown*) This;
887 object->ref = 1;
888 object->myDesc.Width = Width;
889 object->myDesc.Height = Height;
890 object->myDesc.Format = Format;
891 object->myDesc.Type = D3DRTYPE_SURFACE;
892 object->myDesc.Usage = D3DUSAGE_RENDERTARGET;
893 object->myDesc.Pool = D3DPOOL_DEFAULT;
894 object->myDesc.MultiSampleType = MultiSample;
895 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
896 if (Format == D3DFMT_DXT1) {
897 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
898 } else {
899 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
901 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
902 object->lockable = Lockable;
903 object->locked = FALSE;
904 memset(&object->lockedRect, 0, sizeof(RECT));
905 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
907 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);
908 return D3D_OK;
910 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
911 IDirect3DSurface8Impl *object;
913 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
915 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
916 if (NULL == object) {
917 *ppSurface = NULL;
918 return D3DERR_OUTOFVIDEOMEMORY;
920 *ppSurface = (LPDIRECT3DSURFACE8) object;
921 object->lpVtbl = &Direct3DSurface8_Vtbl;
922 object->Device = This;
923 object->ResourceType = D3DRTYPE_SURFACE;
924 object->Container = (IUnknown*) This;
926 object->ref = 1;
927 object->myDesc.Width = Width;
928 object->myDesc.Height = Height;
929 object->myDesc.Format = Format;
930 object->myDesc.Type = D3DRTYPE_SURFACE;
931 object->myDesc.Usage = D3DUSAGE_DEPTHSTENCIL;
932 object->myDesc.Pool = D3DPOOL_DEFAULT;
933 object->myDesc.MultiSampleType = MultiSample;
934 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
935 if (Format == D3DFMT_DXT1) {
936 object->myDesc.Size = (Width * object->bytesPerPixel)/2 * Height; /* DXT1 is half byte per pixel */
937 } else {
938 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
940 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
941 object->lockable = (D3DFMT_D16_LOCKABLE == Format) ? TRUE : FALSE;
942 object->locked = FALSE;
943 memset(&object->lockedRect, 0, sizeof(RECT));
944 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
946 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);
947 return D3D_OK;
949 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
950 IDirect3DSurface8Impl *object;
952 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
954 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
955 *ppSurface = (LPDIRECT3DSURFACE8) object;
956 object->lpVtbl = &Direct3DSurface8_Vtbl;
957 object->Device = This;
958 object->ResourceType = D3DRTYPE_SURFACE;
959 object->Container = (IUnknown*) This;
961 object->ref = 1;
962 object->myDesc.Width = Width;
963 object->myDesc.Height = Height;
964 object->myDesc.Format = Format;
965 object->myDesc.Type = D3DRTYPE_SURFACE;
966 object->myDesc.Usage = 0;
967 object->myDesc.Pool = D3DPOOL_SYSTEMMEM;
968 object->bytesPerPixel = D3DFmtGetBpp(This, Format);
969 /* DXTn mipmaps use the same number of 'levels' down to eg. 8x1, but since
970 it is based around 4x4 pixel blocks it requires padding, so allocate enough
971 space! */
972 if (Format == D3DFMT_DXT1) {
973 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4)) / 2; /* DXT1 is half byte per pixel */
974 } else if (Format == D3DFMT_DXT2 || Format == D3DFMT_DXT3 ||
975 Format == D3DFMT_DXT4 || Format == D3DFMT_DXT5) {
976 object->myDesc.Size = ((max(Width,4) * object->bytesPerPixel) * max(Height,4));
977 } else {
978 object->myDesc.Size = (Width * object->bytesPerPixel) * Height;
980 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->myDesc.Size);
981 object->lockable = TRUE;
982 object->locked = FALSE;
983 memset(&object->lockedRect, 0, sizeof(RECT));
984 IDirect3DSurface8Impl_CleanDirtyRect((LPDIRECT3DSURFACE8) object);
986 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);
987 return D3D_OK;
989 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface,
990 IDirect3DSurface8* pSourceSurface, CONST RECT* pSourceRectsArray, UINT cRects,
991 IDirect3DSurface8* pDestinationSurface, CONST POINT* pDestPointsArray) {
993 HRESULT rc = D3D_OK;
994 IDirect3DBaseTexture8* texture = NULL;
997 IDirect3DSurface8Impl* src = (IDirect3DSurface8Impl*) pSourceSurface;
998 IDirect3DSurface8Impl* dst = (IDirect3DSurface8Impl*) pDestinationSurface;
1000 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1001 TRACE("(%p) pSrcSur=%p, pSourceRects=%p, cRects=%d, pDstSur=%p, pDestPtsArr=%p\n", This,
1002 pSourceSurface, pSourceRectsArray, cRects, pDestinationSurface, pDestPointsArray);
1004 /* Note: Not sure about the d3dfmt_unknown bit, but seems to avoid a problem inside
1005 a sample and doesn't seem to break anything as far as I can tell */
1006 if (src->myDesc.Format != dst->myDesc.Format && (dst->myDesc.Format != D3DFMT_UNKNOWN)) {
1007 TRACE("Formats do not match (%x,%s) / (%x,%s)\n",
1008 src->myDesc.Format, debug_d3dformat(src->myDesc.Format),
1009 dst->myDesc.Format, debug_d3dformat(dst->myDesc.Format));
1010 rc = D3DERR_INVALIDCALL;
1012 } else if (dst->myDesc.Format == D3DFMT_UNKNOWN) {
1013 TRACE("Converting dest to same format as source, since dest was unknown\n");
1014 dst->myDesc.Format = src->myDesc.Format;
1016 /* Convert container as well */
1017 rc = IDirect3DSurface8Impl_GetContainer((LPDIRECT3DSURFACE8) dst, &IID_IDirect3DBaseTexture8, (void**) &texture); /* FIXME: Which refid? */
1018 if (SUCCEEDED(rc) && NULL != texture) {
1019 ((IDirect3DBaseTexture8Impl*) texture)->format = src->myDesc.Format;
1020 /** Releasing texture after GetContainer */
1021 IDirect3DBaseTexture8_Release(texture);
1022 texture = NULL;
1026 /* Quick if complete copy ... */
1027 if (SUCCEEDED(rc)) {
1028 if (cRects == 0 && pSourceRectsArray == NULL && pDestPointsArray == NULL) {
1030 if (src->myDesc.Width == dst->myDesc.Width && src->myDesc.Height == dst->myDesc.Height) {
1032 D3DLOCKED_RECT lrSrc;
1033 D3DLOCKED_RECT lrDst;
1034 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, NULL, D3DLOCK_READONLY);
1035 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, NULL, 0L);
1036 TRACE("Locked src and dst, Direct copy as surfaces are equal, w=%d, h=%d\n", dst->myDesc.Width, dst->myDesc.Height);
1038 memcpy(lrDst.pBits, lrSrc.pBits, src->myDesc.Size);
1040 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1041 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1042 TRACE("Unlocked src and dst\n");
1044 } else {
1046 FIXME("Wanted to copy all surfaces but size not compatible\n");
1047 rc = D3DERR_INVALIDCALL;
1051 } else {
1053 if (NULL != pSourceRectsArray && NULL != pDestPointsArray) {
1055 int bytesPerPixel = ((IDirect3DSurface8Impl*) pSourceSurface)->bytesPerPixel;
1056 unsigned int i;
1058 /* Copy rect by rect */
1059 for (i = 0; i < cRects; i++) {
1060 CONST RECT* r = &pSourceRectsArray[i];
1061 CONST POINT* p = &pDestPointsArray[i];
1062 int copyperline;
1063 int j;
1064 D3DLOCKED_RECT lrSrc;
1065 D3DLOCKED_RECT lrDst;
1066 RECT dest_rect;
1068 TRACE("Copying rect %d (%ld,%ld),(%ld,%ld) -> (%ld,%ld)\n", i, r->left, r->top, r->right, r->bottom, p->x, p->y);
1069 if (src->myDesc.Format == D3DFMT_DXT1) {
1070 copyperline = ((r->right - r->left) * bytesPerPixel)/2; /* DXT1 is half byte per pixel */
1071 } else {
1072 copyperline = ((r->right - r->left) * bytesPerPixel);
1074 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) src, &lrSrc, r, D3DLOCK_READONLY);
1075 dest_rect.left = p->x;
1076 dest_rect.top = p->y;
1077 dest_rect.right = p->x + (r->right - r->left);
1078 dest_rect.bottom= p->y + (r->bottom - r->top);
1079 IDirect3DSurface8Impl_LockRect((LPDIRECT3DSURFACE8) dst, &lrDst, &dest_rect, 0L);
1080 TRACE("Locked src and dst\n");
1082 /* Find where to start */
1083 for (j = 0; j < (r->bottom - r->top - 1); j++) {
1084 memcpy((char*) lrDst.pBits + (j * lrDst.Pitch), (char*) lrSrc.pBits + (j * lrSrc.Pitch), copyperline);
1086 IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) src);
1087 rc = IDirect3DSurface8Impl_UnlockRect((LPDIRECT3DSURFACE8) dst);
1088 TRACE("Unlocked src and dst\n");
1090 } else {
1091 FIXME("Wanted to copy partial surfaces not implemented\n");
1092 rc = D3DERR_INVALIDCALL;
1097 return rc;
1099 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
1100 IDirect3DBaseTexture8Impl* src = (IDirect3DBaseTexture8Impl*) pSourceTexture;
1101 IDirect3DBaseTexture8Impl* dst = (IDirect3DBaseTexture8Impl*) pDestinationTexture;
1102 D3DRESOURCETYPE srcType;
1103 D3DRESOURCETYPE dstType;
1105 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1106 TRACE("(%p) : first try\n", This);
1108 srcType = IDirect3DBaseTexture8Impl_GetType(pSourceTexture);
1109 dstType = IDirect3DBaseTexture8Impl_GetType(pDestinationTexture);
1111 if (srcType != dstType) {
1112 return D3DERR_INVALIDCALL;
1114 if (D3DPOOL_SYSTEMMEM != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) src)) {
1115 return D3DERR_INVALIDCALL;
1117 if (D3DPOOL_DEFAULT != IDirect3DResource8Impl_GetPool((LPDIRECT3DRESOURCE8) dst)) {
1118 return D3DERR_INVALIDCALL;
1120 if (IDirect3DBaseTexture8Impl_IsDirty(pSourceTexture)) {
1121 /** Only copy Dirty textures */
1122 DWORD srcLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pSourceTexture);
1123 DWORD dstLevelCnt = IDirect3DBaseTexture8Impl_GetLevelCount(pDestinationTexture);
1124 DWORD skipLevels = (dstLevelCnt < srcLevelCnt) ? srcLevelCnt - dstLevelCnt : 0;
1125 UINT i, j;
1127 for (i = skipLevels; i < srcLevelCnt; ++i) {
1128 HRESULT hr;
1130 switch (srcType) {
1131 case D3DRTYPE_TEXTURE:
1133 IDirect3DSurface8* srcSur = NULL;
1134 IDirect3DSurface8* dstSur = NULL;
1135 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) src, i, &srcSur);
1136 hr = IDirect3DTexture8Impl_GetSurfaceLevel((LPDIRECT3DTEXTURE8) dst, i - skipLevels, &dstSur);
1138 /* Fixme: Work out how to just do the dirty regions (src or dst dirty region, and what
1139 about dst with less levels than the source?) */
1140 IDirect3DDevice8Impl_CopyRects(iface, srcSur, NULL, 0, dstSur, NULL);
1142 IDirect3DSurface8Impl_Release(srcSur);
1143 IDirect3DSurface8Impl_Release(dstSur);
1145 break;
1146 case D3DRTYPE_VOLUMETEXTURE:
1148 FIXME("D3DRTYPE_VOLUMETEXTURE reload currently not implemented\n");
1150 break;
1151 case D3DRTYPE_CUBETEXTURE:
1153 IDirect3DSurface8* srcSur = NULL;
1154 IDirect3DSurface8* dstSur = NULL;
1155 for (j = 0; j < 5; ++j) {
1156 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) src, j, i, &srcSur);
1157 hr = IDirect3DCubeTexture8Impl_GetCubeMapSurface((LPDIRECT3DCUBETEXTURE8) dst, j, i - skipLevels, &srcSur);
1158 FIXME("D3DRTYPE_CUBETEXTURE does not support UpdateTexture yet\n");
1159 IDirect3DSurface8Impl_Release(srcSur);
1160 IDirect3DSurface8Impl_Release(dstSur);
1163 break;
1164 default:
1165 break;
1168 IDirect3DBaseTexture8Impl_SetDirty(pSourceTexture, FALSE);
1171 return D3D_OK;
1173 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
1174 HRESULT hr;
1175 D3DLOCKED_RECT lockedRect;
1176 RECT wantedRect;
1177 GLint prev_store;
1178 GLenum prev_read;
1180 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1182 FIXME("(%p) : Should return whole screen, only returns GL context window in top left corner\n", This);
1184 if (D3DFMT_A8R8G8B8 != ((IDirect3DSurface8Impl*) pDestSurface)->myDesc.Format) {
1185 ERR("(%p) : surface(%p) has an invalid format\n", This, pDestSurface);
1186 return D3DERR_INVALIDCALL;
1189 wantedRect.left = 0;
1190 wantedRect.top = 0;
1191 wantedRect.right = This->PresentParms.BackBufferWidth;
1192 wantedRect.bottom = This->PresentParms.BackBufferHeight;
1194 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
1195 if (FAILED(hr)) {
1196 ERR("(%p) : cannot lock surface\n", This);
1197 return D3DERR_INVALIDCALL;
1200 ENTER_GL();
1202 glFlush();
1203 vcheckGLcall("glFlush");
1204 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1205 vcheckGLcall("glIntegerv");
1206 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
1207 vcheckGLcall("glIntegerv");
1209 glReadBuffer(GL_FRONT);
1210 vcheckGLcall("glReadBuffer");
1211 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
1212 vcheckGLcall("glPixelStorei");
1213 /* stupid copy */
1215 unsigned long j;
1216 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
1217 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
1218 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
1219 vcheckGLcall("glReadPixels");
1222 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
1223 vcheckGLcall("glPixelStorei");
1224 glReadBuffer(prev_read);
1225 vcheckGLcall("glReadBuffer");
1227 LEAVE_GL();
1229 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
1230 return hr;
1232 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
1233 HRESULT hr = D3D_OK;
1234 D3DVIEWPORT8 viewport;
1236 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1238 /* If pRenderTarget == NULL, it seems to default to back buffer */
1239 if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface8*)This->backBuffer;
1241 /* For ease of code later on, handle a null depth as leave alone
1242 - Have not tested real d3d for this case but doing this avoids
1243 numerous null pointer checks */
1244 if (pNewZStencil == NULL) pNewZStencil = (IDirect3DSurface8*)This->stencilBufferTarget;
1246 /* If we are trying to set what we already have, don't bother */
1247 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
1248 TRACE("Trying to do a NOP SetRenderTarget operation\n");
1249 } else {
1250 /* Otherwise, set the render target up */
1251 TRACE("(%p) : newRender@%p newZStencil@%p (default is backbuffer=(%p))\n", This, pRenderTarget, pNewZStencil, This->backBuffer);
1252 IDirect3DDevice8Impl_CleanRender(iface);
1253 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
1256 if (SUCCEEDED(hr)) {
1257 /* Finally, reset the viewport as the MSDN states. */
1258 viewport.Height = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Height;
1259 viewport.Width = ((IDirect3DSurface8Impl*)pRenderTarget)->myDesc.Width;
1260 viewport.X = 0;
1261 viewport.Y = 0;
1262 viewport.MaxZ = 1.0f;
1263 viewport.MinZ = 0.0f;
1264 IDirect3DDevice8Impl_SetViewport(iface, &viewport);
1267 return hr;
1270 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
1271 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1273 TRACE("(%p)->returning (%p) default is backbuffer=(%p)\n", This, This->renderTarget, This->backBuffer);
1275 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
1276 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1278 return D3D_OK;
1281 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1282 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1284 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1286 /* Note inc ref on returned surface */
1287 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1288 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1290 return D3D_OK;
1293 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1294 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1295 return IWineD3DDevice_BeginScene(This->WineD3DDevice);
1298 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1299 IDirect3DBaseTexture8* cont = NULL;
1300 HRESULT hr;
1301 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1302 TRACE("(%p)\n", This);
1304 ENTER_GL();
1306 glFlush();
1307 checkGLcall("glFlush");
1309 #if 0 /* Useful for debugging sometimes! */
1310 printf("Hit Enter ...\n");
1311 getchar();
1312 #endif
1314 if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
1315 #if 0
1316 GLenum prev_read;
1317 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1318 vcheckGLcall("glIntegerv");
1319 glReadBuffer(GL_FRONT);
1320 vcheckGLcall("glReadBuffer");
1322 long j;
1323 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1325 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1326 pitch = pitch / 2;
1328 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1329 glReadPixels(0,
1330 This->renderTarget->myDesc.Height - j - 1,
1331 This->renderTarget->myDesc.Width,
1333 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1334 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1335 This->renderTarget->allocatedMemory + j * pitch);
1336 vcheckGLcall("glReadPixels");
1339 glReadBuffer(prev_read);
1340 vcheckGLcall("glReadBuffer");
1341 #endif
1343 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1344 if (SUCCEEDED(hr) && NULL != cont) {
1345 /** always dirtify for now. we must find a better way to see that surface have been modified */
1346 This->renderTarget->inPBuffer = TRUE;
1347 This->renderTarget->inTexture = FALSE;
1348 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1349 IDirect3DBaseTexture8_PreLoad(cont);
1350 This->renderTarget->inPBuffer = FALSE;
1351 IDirect3DBaseTexture8Impl_Release(cont);
1352 cont = NULL;
1356 LEAVE_GL();
1357 return D3D_OK;
1359 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1360 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1362 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1363 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1364 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1365 GLbitfield glMask = 0;
1366 GLboolean old_ztest;
1367 GLfloat old_z_clear_value;
1368 GLint old_stencil_clear_value;
1369 GLfloat old_color_clear_value[4];
1370 unsigned int i;
1371 CONST D3DRECT* curRect;
1373 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1374 Count, pRects, Flags, Z, Stencil);
1376 ENTER_GL();
1377 glEnable(GL_SCISSOR_TEST);
1378 checkGLcall("glEnable GL_SCISSOR_TEST");
1379 if (Count > 0 && pRects) {
1380 curRect = pRects;
1381 } else {
1382 curRect = NULL;
1385 /* Only set the values up once, as they are not changing */
1386 if (Flags & D3DCLEAR_STENCIL) {
1387 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1388 glClearStencil(Stencil);
1389 checkGLcall("glClearStencil");
1390 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1391 glStencilMask(0xFFFFFFFF);
1394 if (Flags & D3DCLEAR_ZBUFFER) {
1395 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1396 glDepthMask(GL_TRUE);
1397 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1398 glClearDepth(Z);
1399 checkGLcall("glClearDepth");
1400 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1403 if (Flags & D3DCLEAR_TARGET) {
1404 TRACE("Clearing screen with glClear to color %lx\n", Color);
1405 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1406 glClearColor(((Color >> 16) & 0xFF) / 255.0f,
1407 ((Color >> 8) & 0xFF) / 255.0f,
1408 ((Color >> 0) & 0xFF) / 255.0f,
1409 ((Color >> 24) & 0xFF) / 255.0f);
1410 checkGLcall("glClearColor");
1412 /* Clear ALL colors! */
1413 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1414 glMask = glMask | GL_COLOR_BUFFER_BIT;
1417 /* Now process each rect in turn */
1418 for (i = 0; i < Count || i == 0; i++) {
1420 if (curRect) {
1421 /* Note gl uses lower left, width/height */
1422 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1423 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1424 curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1425 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1426 glScissor(curRect->x1, (This->renderTarget->myDesc.Height - curRect->y2),
1427 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1428 checkGLcall("glScissor");
1429 } else {
1430 glScissor(This->StateBlock->viewport.X,
1431 (This->renderTarget->myDesc.Height - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1432 This->StateBlock->viewport.Width,
1433 This->StateBlock->viewport.Height);
1434 checkGLcall("glScissor");
1437 /* Clear the selected rectangle (or full screen) */
1438 glClear(glMask);
1439 checkGLcall("glClear");
1441 /* Step to the next rectangle */
1442 if (curRect) curRect = curRect + sizeof(D3DRECT);
1445 /* Restore the old values (why..?) */
1446 if (Flags & D3DCLEAR_STENCIL) {
1447 glClearStencil(old_stencil_clear_value);
1448 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1450 if (Flags & D3DCLEAR_ZBUFFER) {
1451 glDepthMask(old_ztest);
1452 glClearDepth(old_z_clear_value);
1454 if (Flags & D3DCLEAR_TARGET) {
1455 glClearColor(old_color_clear_value[0],
1456 old_color_clear_value[1],
1457 old_color_clear_value[2],
1458 old_color_clear_value[3]);
1459 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1460 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1461 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1462 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1465 glDisable(GL_SCISSOR_TEST);
1466 checkGLcall("glDisable");
1467 LEAVE_GL();
1469 return D3D_OK;
1471 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1472 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1473 unsigned int k;
1475 /* Most of this routine, comments included copied from ddraw tree initially: */
1476 TRACE("(%p) : State=%d\n", This, d3dts);
1478 /* Handle recording of state blocks */
1479 if (This->isRecordingState) {
1480 TRACE("Recording... not performing anything\n");
1481 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1482 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1483 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1484 return D3D_OK;
1488 * if the new matrix is the same as the current one,
1489 * we cut off any further processing. this seems to be a reasonable
1490 * optimization because as was noticed, some apps (warcraft3 for example)
1491 * tend towards setting the same matrix repeatedly for some dumb reason.
1493 * From here on we assume that the new matrix is different, wherever it matters
1494 * but note
1496 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1497 TRACE("The app is setting the same matrix over again\n");
1498 return D3D_OK;
1499 } else {
1500 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1504 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1505 where ViewMat = Camera space, WorldMat = world space.
1507 In OpenGL, camera and world space is combined into GL_MODELVIEW
1508 matrix. The Projection matrix stay projection matrix.
1511 /* Capture the times we can just ignore the change */
1512 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1513 This->modelview_valid = FALSE;
1514 return D3D_OK;
1516 } else if (d3dts == D3DTS_PROJECTION) {
1517 This->proj_valid = FALSE;
1518 return D3D_OK;
1520 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1521 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1522 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1523 return D3D_OK;
1526 /* Chances are we really are going to have to change a matrix */
1527 ENTER_GL();
1529 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1530 if (d3dts < GL_LIMITS(textures)) {
1531 int tex = d3dts - D3DTS_TEXTURE0;
1532 #if defined(GL_VERSION_1_3)
1533 glActiveTexture(GL_TEXTURE0 + tex);
1534 checkGLcall("glActiveTexture");
1535 #else
1536 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1537 checkGLcall("glActiveTextureARB");
1538 #endif
1539 set_texture_matrix((const float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1542 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1544 PLIGHTINFOEL *lightChain = NULL;
1545 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1546 This->modelview_valid = FALSE;
1547 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1548 glMatrixMode(GL_MODELVIEW);
1549 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1550 glPushMatrix();
1551 glLoadMatrixf((const float *)lpmatrix);
1552 checkGLcall("glLoadMatrixf(...)");
1554 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1555 * NOTE: We have to reset the positions even if the light/plane is not currently
1556 * enabled, since the call to enable it will not reset the position.
1557 * NOTE2: Apparently texture transforms do NOT need reapplying
1560 /* Reset lights */
1561 lightChain = This->StateBlock->lights;
1562 while (lightChain && lightChain->glIndex != -1) {
1563 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1564 checkGLcall("glLightfv posn");
1565 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1566 checkGLcall("glLightfv dirn");
1567 lightChain = lightChain->next;
1569 /* Reset Clipping Planes if clipping is enabled */
1570 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1571 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1572 checkGLcall("glClipPlane");
1574 glPopMatrix();
1576 } else { /* What was requested!?? */
1577 WARN("invalid matrix specified: %i\n", d3dts);
1581 /* Release lock, all done */
1582 LEAVE_GL();
1583 return D3D_OK;
1586 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1587 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1588 TRACE("(%p) : for State %d\n", This, State);
1589 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1590 return D3D_OK;
1593 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1594 D3DMATRIX *mat = NULL;
1595 D3DMATRIX temp;
1597 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1598 but works regardless of recording being on.
1599 If this is found to be wrong, change to StateBlock. */
1600 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1601 TRACE("(%p) : For state %u\n", This, State);
1603 if (State < HIGHEST_TRANSFORMSTATE)
1605 mat = &This->UpdateStateBlock->transforms[State];
1606 } else {
1607 FIXME("Unhandled transform state!!\n");
1610 /* Copied from ddraw code: */
1611 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);
1612 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);
1613 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);
1614 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);
1616 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);
1617 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);
1618 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);
1619 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);
1621 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);
1622 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);
1623 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);
1624 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);
1626 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);
1627 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);
1628 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);
1629 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);
1631 /* Apply change via set transform - will reapply to eg. lights this way */
1632 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1633 return D3D_OK;
1635 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1636 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1638 TRACE("(%p)\n", This);
1639 This->UpdateStateBlock->Changed.viewport = TRUE;
1640 This->UpdateStateBlock->Set.viewport = TRUE;
1641 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1643 /* Handle recording of state blocks */
1644 if (This->isRecordingState) {
1645 TRACE("Recording... not performing anything\n");
1646 return D3D_OK;
1649 ENTER_GL();
1651 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1652 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1654 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1655 checkGLcall("glDepthRange");
1656 /* Note: GL requires lower left, DirectX supplies upper left */
1657 glViewport(pViewport->X, (This->renderTarget->myDesc.Height - (pViewport->Y + pViewport->Height)),
1658 pViewport->Width, pViewport->Height);
1659 checkGLcall("glViewport");
1661 LEAVE_GL();
1663 return D3D_OK;
1666 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1667 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1668 TRACE("(%p)\n", This);
1669 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1670 return D3D_OK;
1673 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1674 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1676 This->UpdateStateBlock->Changed.material = TRUE;
1677 This->UpdateStateBlock->Set.material = TRUE;
1678 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1680 /* Handle recording of state blocks */
1681 if (This->isRecordingState) {
1682 TRACE("Recording... not performing anything\n");
1683 return D3D_OK;
1686 ENTER_GL();
1687 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1688 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1689 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1690 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1691 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1693 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1694 checkGLcall("glMaterialfv");
1695 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1696 checkGLcall("glMaterialfv");
1698 /* Only change material color if specular is enabled, otherwise it is set to black */
1699 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1700 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1701 checkGLcall("glMaterialfv");
1702 } else {
1703 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1704 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1705 checkGLcall("glMaterialfv");
1707 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1708 checkGLcall("glMaterialfv");
1709 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1710 checkGLcall("glMaterialf");
1712 LEAVE_GL();
1713 return D3D_OK;
1715 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1716 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1717 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1718 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1719 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1720 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1721 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1722 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1723 return D3D_OK;
1726 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1727 you can reference any indexes you want as long as that number max are enabled are any
1728 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1729 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1730 but when recording, just build a chain pretty much of commands to be replayed. */
1732 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1733 float rho;
1734 PLIGHTINFOEL *object, *temp;
1736 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1737 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1739 /* If recording state block, just add to end of lights chain */
1740 if (This->isRecordingState) {
1741 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1742 if (NULL == object) {
1743 return D3DERR_OUTOFVIDEOMEMORY;
1745 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1746 object->OriginalIndex = Index;
1747 object->glIndex = -1;
1748 object->changed = TRUE;
1750 /* Add to the END of the chain of lights changes to be replayed */
1751 if (This->UpdateStateBlock->lights == NULL) {
1752 This->UpdateStateBlock->lights = object;
1753 } else {
1754 temp = This->UpdateStateBlock->lights;
1755 while (temp->next != NULL) temp=temp->next;
1756 temp->next = object;
1758 TRACE("Recording... not performing anything more\n");
1759 return D3D_OK;
1762 /* Ok, not recording any longer so do real work */
1763 object = This->StateBlock->lights;
1764 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1766 /* If we didn't find it in the list of lights, time to add it */
1767 if (object == NULL) {
1768 PLIGHTINFOEL *insertAt,*prevPos;
1770 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1771 if (NULL == object) {
1772 return D3DERR_OUTOFVIDEOMEMORY;
1774 object->OriginalIndex = Index;
1775 object->glIndex = -1;
1777 /* Add it to the front of list with the idea that lights will be changed as needed
1778 BUT after any lights currently assigned GL indexes */
1779 insertAt = This->StateBlock->lights;
1780 prevPos = NULL;
1781 while (insertAt != NULL && insertAt->glIndex != -1) {
1782 prevPos = insertAt;
1783 insertAt = insertAt->next;
1786 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1787 This->StateBlock->lights = object;
1788 } else if (insertAt == NULL) { /* End of list */
1789 prevPos->next = object;
1790 object->prev = prevPos;
1791 } else { /* Middle of chain */
1792 if (prevPos == NULL) {
1793 This->StateBlock->lights = object;
1794 } else {
1795 prevPos->next = object;
1797 object->prev = prevPos;
1798 object->next = insertAt;
1799 insertAt->prev = object;
1803 /* Initialze the object */
1804 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,
1805 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1806 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1807 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1808 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1809 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1810 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1812 /* Save away the information */
1813 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1815 switch (pLight->Type) {
1816 case D3DLIGHT_POINT:
1817 /* Position */
1818 object->lightPosn[0] = pLight->Position.x;
1819 object->lightPosn[1] = pLight->Position.y;
1820 object->lightPosn[2] = pLight->Position.z;
1821 object->lightPosn[3] = 1.0f;
1822 object->cutoff = 180.0f;
1823 /* FIXME: Range */
1824 break;
1826 case D3DLIGHT_DIRECTIONAL:
1827 /* Direction */
1828 object->lightPosn[0] = -pLight->Direction.x;
1829 object->lightPosn[1] = -pLight->Direction.y;
1830 object->lightPosn[2] = -pLight->Direction.z;
1831 object->lightPosn[3] = 0.0;
1832 object->exponent = 0.0f;
1833 object->cutoff = 180.0f;
1834 break;
1836 case D3DLIGHT_SPOT:
1837 /* Position */
1838 object->lightPosn[0] = pLight->Position.x;
1839 object->lightPosn[1] = pLight->Position.y;
1840 object->lightPosn[2] = pLight->Position.z;
1841 object->lightPosn[3] = 1.0;
1843 /* Direction */
1844 object->lightDirn[0] = pLight->Direction.x;
1845 object->lightDirn[1] = pLight->Direction.y;
1846 object->lightDirn[2] = pLight->Direction.z;
1847 object->lightDirn[3] = 1.0;
1850 * opengl-ish and d3d-ish spot lights use too different models for the
1851 * light "intensity" as a function of the angle towards the main light direction,
1852 * so we only can approximate very roughly.
1853 * however spot lights are rather rarely used in games (if ever used at all).
1854 * furthermore if still used, probably nobody pays attention to such details.
1856 if (pLight->Falloff == 0) {
1857 rho = 6.28f;
1858 } else {
1859 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1861 if (rho < 0.0001) rho = 0.0001f;
1862 object->exponent = -0.3/log(cos(rho/2));
1863 object->cutoff = pLight->Phi*90/M_PI;
1865 /* FIXME: Range */
1866 break;
1868 default:
1869 FIXME("Unrecognized light type %d\n", pLight->Type);
1872 /* Update the live definitions if the light is currently assigned a glIndex */
1873 if (object->glIndex != -1) {
1874 setup_light(iface, object->glIndex, object);
1876 return D3D_OK;
1878 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1879 PLIGHTINFOEL *lightInfo = NULL;
1880 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1881 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1883 /* Locate the light in the live lights */
1884 lightInfo = This->StateBlock->lights;
1885 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1887 if (lightInfo == NULL) {
1888 TRACE("Light information requested but light not defined\n");
1889 return D3DERR_INVALIDCALL;
1892 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1893 return D3D_OK;
1895 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1896 PLIGHTINFOEL *lightInfo = NULL;
1897 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1898 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1900 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1901 if (This->isRecordingState) {
1902 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1903 if (NULL == lightInfo) {
1904 return D3DERR_OUTOFVIDEOMEMORY;
1906 lightInfo->OriginalIndex = Index;
1907 lightInfo->glIndex = -1;
1908 lightInfo->enabledChanged = TRUE;
1910 /* Add to the END of the chain of lights changes to be replayed */
1911 if (This->UpdateStateBlock->lights == NULL) {
1912 This->UpdateStateBlock->lights = lightInfo;
1913 } else {
1914 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1915 while (temp->next != NULL) temp=temp->next;
1916 temp->next = lightInfo;
1918 TRACE("Recording... not performing anything more\n");
1919 return D3D_OK;
1922 /* Not recording... So, locate the light in the live lights */
1923 lightInfo = This->StateBlock->lights;
1924 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1926 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1927 if (lightInfo == NULL) {
1928 D3DLIGHT8 lightParms;
1929 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1930 wait until someone confirms it seems to work! */
1931 TRACE("Light enabled requested but light not defined, so defining one!\n");
1932 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1933 lightParms.Diffuse.r = 1.0;
1934 lightParms.Diffuse.g = 1.0;
1935 lightParms.Diffuse.b = 1.0;
1936 lightParms.Diffuse.a = 0.0;
1937 lightParms.Specular.r = 0.0;
1938 lightParms.Specular.g = 0.0;
1939 lightParms.Specular.b = 0.0;
1940 lightParms.Specular.a = 0.0;
1941 lightParms.Ambient.r = 0.0;
1942 lightParms.Ambient.g = 0.0;
1943 lightParms.Ambient.b = 0.0;
1944 lightParms.Ambient.a = 0.0;
1945 lightParms.Position.x = 0.0;
1946 lightParms.Position.y = 0.0;
1947 lightParms.Position.z = 0.0;
1948 lightParms.Direction.x = 0.0;
1949 lightParms.Direction.y = 0.0;
1950 lightParms.Direction.z = 1.0;
1951 lightParms.Range = 0.0;
1952 lightParms.Falloff = 0.0;
1953 lightParms.Attenuation0 = 0.0;
1954 lightParms.Attenuation1 = 0.0;
1955 lightParms.Attenuation2 = 0.0;
1956 lightParms.Theta = 0.0;
1957 lightParms.Phi = 0.0;
1958 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1960 /* Search for it again! Should be fairly quick as near head of list */
1961 lightInfo = This->StateBlock->lights;
1962 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1963 if (lightInfo == NULL) {
1964 FIXME("Adding default lights has failed dismally\n");
1965 return D3DERR_INVALIDCALL;
1969 /* OK, we now have a light... */
1970 if (Enable == FALSE) {
1972 /* If we are disabling it, check it was enabled, and
1973 still only do something if it has assigned a glIndex (which it should have!) */
1974 if (lightInfo->lightEnabled && (lightInfo->glIndex != -1)) {
1975 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1976 ENTER_GL();
1977 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1978 checkGLcall("glDisable GL_LIGHT0+Index");
1979 LEAVE_GL();
1980 } else {
1981 TRACE("Nothing to do as light was not enabled\n");
1983 lightInfo->lightEnabled = FALSE;
1984 } else {
1986 /* We are enabling it. If it is enabled, its really simple */
1987 if (lightInfo->lightEnabled) {
1988 /* nop */
1989 TRACE("Nothing to do as light was enabled\n");
1991 /* If it already has a glIndex, its still simple */
1992 } else if (lightInfo->glIndex != -1) {
1993 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1994 lightInfo->lightEnabled = TRUE;
1995 ENTER_GL();
1996 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1997 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1998 LEAVE_GL();
2000 /* Otherwise got to find space - lights are ordered gl indexes first */
2001 } else {
2002 PLIGHTINFOEL *bsf = NULL;
2003 PLIGHTINFOEL *pos = This->StateBlock->lights;
2004 PLIGHTINFOEL *prev = NULL;
2005 int Index= 0;
2006 int glIndex = -1;
2008 /* Try to minimize changes as much as possible */
2009 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
2011 /* Try to remember which index can be replaced if necessary */
2012 if (bsf==NULL && pos->lightEnabled == FALSE) {
2013 /* Found a light we can replace, save as best replacement */
2014 bsf = pos;
2017 /* Step to next space */
2018 prev = pos;
2019 pos = pos->next;
2020 Index ++;
2023 /* If we have too many active lights, fail the call */
2024 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
2025 FIXME("Program requests too many concurrent lights\n");
2026 return D3DERR_INVALIDCALL;
2028 /* If we have allocated all lights, but not all are enabled,
2029 reuse one which is not enabled */
2030 } else if (Index == This->maxConcurrentLights) {
2031 /* use bsf - Simply swap the new light and the BSF one */
2032 PLIGHTINFOEL *bsfNext = bsf->next;
2033 PLIGHTINFOEL *bsfPrev = bsf->prev;
2035 /* Sort out ends */
2036 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
2037 if (bsf->prev != NULL) {
2038 bsf->prev->next = lightInfo;
2039 } else {
2040 This->StateBlock->lights = lightInfo;
2043 /* If not side by side, lots of chains to update */
2044 if (bsf->next != lightInfo) {
2045 lightInfo->prev->next = bsf;
2046 bsf->next->prev = lightInfo;
2047 bsf->next = lightInfo->next;
2048 bsf->prev = lightInfo->prev;
2049 lightInfo->next = bsfNext;
2050 lightInfo->prev = bsfPrev;
2052 } else {
2053 /* Simple swaps */
2054 bsf->prev = lightInfo;
2055 bsf->next = lightInfo->next;
2056 lightInfo->next = bsf;
2057 lightInfo->prev = bsfPrev;
2061 /* Update states */
2062 glIndex = bsf->glIndex;
2063 bsf->glIndex = -1;
2064 lightInfo->glIndex = glIndex;
2065 lightInfo->lightEnabled = TRUE;
2067 /* Finally set up the light in gl itself */
2068 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
2069 ENTER_GL();
2070 setup_light(iface, glIndex, lightInfo);
2071 glEnable(GL_LIGHT0 + glIndex);
2072 checkGLcall("glEnable GL_LIGHT0 new setup");
2073 LEAVE_GL();
2075 /* If we reached the end of the allocated lights, with space in the
2076 gl lights, setup a new light */
2077 } else if (pos->glIndex == -1) {
2079 /* We reached the end of the allocated gl lights, so already
2080 know the index of the next one! */
2081 glIndex = Index;
2082 lightInfo->glIndex = glIndex;
2083 lightInfo->lightEnabled = TRUE;
2085 /* In an ideal world, its already in the right place */
2086 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
2087 /* No need to move it */
2088 } else {
2089 /* Remove this light from the list */
2090 lightInfo->prev->next = lightInfo->next;
2091 if (lightInfo->next != NULL) {
2092 lightInfo->next->prev = lightInfo->prev;
2095 /* Add in at appropriate place (inbetween prev and pos) */
2096 lightInfo->prev = prev;
2097 lightInfo->next = pos;
2098 if (prev == NULL) {
2099 This->StateBlock->lights = lightInfo;
2100 } else {
2101 prev->next = lightInfo;
2103 if (pos != NULL) {
2104 pos->prev = lightInfo;
2108 /* Finally set up the light in gl itself */
2109 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
2110 ENTER_GL();
2111 setup_light(iface, glIndex, lightInfo);
2112 glEnable(GL_LIGHT0 + glIndex);
2113 checkGLcall("glEnable GL_LIGHT0 new setup");
2114 LEAVE_GL();
2119 return D3D_OK;
2121 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
2123 PLIGHTINFOEL *lightInfo = NULL;
2124 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2125 TRACE("(%p) : for idx(%ld)\n", This, Index);
2127 /* Locate the light in the live lights */
2128 lightInfo = This->StateBlock->lights;
2129 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
2131 if (lightInfo == NULL) {
2132 TRACE("Light enabled state requested but light not defined\n");
2133 return D3DERR_INVALIDCALL;
2135 *pEnable = lightInfo->lightEnabled;
2136 return D3D_OK;
2138 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
2139 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2140 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
2142 /* Validate Index */
2143 if (Index >= GL_LIMITS(clipplanes)) {
2144 TRACE("Application has requested clipplane this device doesn't support\n");
2145 return D3DERR_INVALIDCALL;
2148 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
2149 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
2150 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
2151 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
2152 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
2153 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
2155 /* Handle recording of state blocks */
2156 if (This->isRecordingState) {
2157 TRACE("Recording... not performing anything\n");
2158 return D3D_OK;
2161 /* Apply it */
2163 ENTER_GL();
2165 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
2166 glMatrixMode(GL_MODELVIEW);
2167 glPushMatrix();
2168 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
2170 TRACE("Clipplane [%f,%f,%f,%f]\n",
2171 This->UpdateStateBlock->clipplane[Index][0],
2172 This->UpdateStateBlock->clipplane[Index][1],
2173 This->UpdateStateBlock->clipplane[Index][2],
2174 This->UpdateStateBlock->clipplane[Index][3]);
2175 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
2176 checkGLcall("glClipPlane");
2178 glPopMatrix();
2180 LEAVE_GL();
2182 return D3D_OK;
2184 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
2185 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2186 TRACE("(%p) : for idx %ld\n", This, Index);
2188 /* Validate Index */
2189 if (Index >= GL_LIMITS(clipplanes)) {
2190 TRACE("Application has requested clipplane this device doesn't support\n");
2191 return D3DERR_INVALIDCALL;
2194 pPlane[0] = This->StateBlock->clipplane[Index][0];
2195 pPlane[1] = This->StateBlock->clipplane[Index][1];
2196 pPlane[2] = This->StateBlock->clipplane[Index][2];
2197 pPlane[3] = This->StateBlock->clipplane[Index][3];
2198 return D3D_OK;
2200 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
2201 union {
2202 DWORD d;
2203 float f;
2204 } tmpvalue;
2205 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2206 DWORD OldValue = This->StateBlock->renderstate[State];
2208 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
2209 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
2210 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
2211 This->UpdateStateBlock->renderstate[State] = Value;
2213 /* Handle recording of state blocks */
2214 if (This->isRecordingState) {
2215 TRACE("Recording... not performing anything\n");
2216 return D3D_OK;
2219 ENTER_GL();
2221 switch (State) {
2222 case D3DRS_FILLMODE :
2223 switch ((D3DFILLMODE) Value) {
2224 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
2225 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
2226 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
2227 default:
2228 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
2230 checkGLcall("glPolygonMode (fillmode)");
2231 break;
2233 case D3DRS_LIGHTING :
2234 if (Value) {
2235 glEnable(GL_LIGHTING);
2236 checkGLcall("glEnable GL_LIGHTING");
2237 } else {
2238 glDisable(GL_LIGHTING);
2239 checkGLcall("glDisable GL_LIGHTING");
2241 break;
2243 case D3DRS_ZENABLE :
2244 switch ((D3DZBUFFERTYPE) Value) {
2245 case D3DZB_FALSE:
2246 glDisable(GL_DEPTH_TEST);
2247 checkGLcall("glDisable GL_DEPTH_TEST");
2248 break;
2249 case D3DZB_TRUE:
2250 glEnable(GL_DEPTH_TEST);
2251 checkGLcall("glEnable GL_DEPTH_TEST");
2252 break;
2253 case D3DZB_USEW:
2254 glEnable(GL_DEPTH_TEST);
2255 checkGLcall("glEnable GL_DEPTH_TEST");
2256 FIXME("W buffer is not well handled\n");
2257 break;
2258 default:
2259 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
2261 break;
2263 case D3DRS_CULLMODE :
2265 /* If we are culling "back faces with clockwise vertices" then
2266 set front faces to be counter clockwise and enable culling
2267 of back faces */
2268 switch ((D3DCULL) Value) {
2269 case D3DCULL_NONE:
2270 glDisable(GL_CULL_FACE);
2271 checkGLcall("glDisable GL_CULL_FACE");
2272 break;
2273 case D3DCULL_CW:
2274 glEnable(GL_CULL_FACE);
2275 checkGLcall("glEnable GL_CULL_FACE");
2276 if (This->renderUpsideDown) {
2277 glFrontFace(GL_CW);
2278 checkGLcall("glFrontFace GL_CW");
2279 } else {
2280 glFrontFace(GL_CCW);
2281 checkGLcall("glFrontFace GL_CCW");
2283 glCullFace(GL_BACK);
2284 break;
2285 case D3DCULL_CCW:
2286 glEnable(GL_CULL_FACE);
2287 checkGLcall("glEnable GL_CULL_FACE");
2288 if (This->renderUpsideDown) {
2289 glFrontFace(GL_CCW);
2290 checkGLcall("glFrontFace GL_CCW");
2291 } else {
2292 glFrontFace(GL_CW);
2293 checkGLcall("glFrontFace GL_CW");
2295 glCullFace(GL_BACK);
2296 break;
2297 default:
2298 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2300 break;
2302 case D3DRS_SHADEMODE :
2303 switch ((D3DSHADEMODE) Value) {
2304 case D3DSHADE_FLAT:
2305 glShadeModel(GL_FLAT);
2306 checkGLcall("glShadeModel");
2307 break;
2308 case D3DSHADE_GOURAUD:
2309 glShadeModel(GL_SMOOTH);
2310 checkGLcall("glShadeModel");
2311 break;
2312 case D3DSHADE_PHONG:
2313 FIXME("D3DSHADE_PHONG isn't supported?\n");
2315 LEAVE_GL();
2316 return D3DERR_INVALIDCALL;
2317 default:
2318 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2320 break;
2322 case D3DRS_DITHERENABLE :
2323 if (Value) {
2324 glEnable(GL_DITHER);
2325 checkGLcall("glEnable GL_DITHER");
2326 } else {
2327 glDisable(GL_DITHER);
2328 checkGLcall("glDisable GL_DITHER");
2330 break;
2332 case D3DRS_ZWRITEENABLE :
2333 if (Value) {
2334 glDepthMask(1);
2335 checkGLcall("glDepthMask");
2336 } else {
2337 glDepthMask(0);
2338 checkGLcall("glDepthMask");
2340 break;
2342 case D3DRS_ZFUNC :
2344 int glParm = GL_LESS;
2346 switch ((D3DCMPFUNC) Value) {
2347 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2348 case D3DCMP_LESS: glParm=GL_LESS; break;
2349 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2350 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2351 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2352 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2353 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2354 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2355 default:
2356 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2358 glDepthFunc(glParm);
2359 checkGLcall("glDepthFunc");
2361 break;
2363 case D3DRS_AMBIENT :
2365 float col[4];
2366 D3DCOLORTOGLFLOAT4(Value, col);
2367 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2368 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2369 checkGLcall("glLightModel for MODEL_AMBIENT");
2372 break;
2374 case D3DRS_ALPHABLENDENABLE :
2375 if (Value) {
2376 glEnable(GL_BLEND);
2377 checkGLcall("glEnable GL_BLEND");
2378 } else {
2379 glDisable(GL_BLEND);
2380 checkGLcall("glDisable GL_BLEND");
2382 break;
2384 case D3DRS_SRCBLEND :
2385 case D3DRS_DESTBLEND :
2387 int newVal = GL_ZERO;
2388 switch (Value) {
2389 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2390 case D3DBLEND_ONE : newVal = GL_ONE; break;
2391 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2392 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2393 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2394 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2395 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2396 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2397 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2398 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2399 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2401 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2402 This->srcBlend = newVal;
2403 This->dstBlend = newVal;
2404 break;
2406 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2407 This->srcBlend = newVal;
2408 This->dstBlend = newVal;
2409 break;
2410 default:
2411 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2414 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2415 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2416 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2417 glBlendFunc(This->srcBlend, This->dstBlend);
2419 checkGLcall("glBlendFunc");
2421 break;
2423 case D3DRS_ALPHATESTENABLE :
2424 if (Value) {
2425 glEnable(GL_ALPHA_TEST);
2426 checkGLcall("glEnable GL_ALPHA_TEST");
2427 } else {
2428 glDisable(GL_ALPHA_TEST);
2429 checkGLcall("glDisable GL_ALPHA_TEST");
2431 break;
2433 case D3DRS_ALPHAFUNC :
2435 int glParm = GL_LESS;
2436 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2438 switch ((D3DCMPFUNC) Value) {
2439 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2440 case D3DCMP_LESS: glParm = GL_LESS; break;
2441 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2442 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2443 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2444 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2445 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2446 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2447 default:
2448 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2450 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2451 glAlphaFunc(glParm, ref);
2452 This->alphafunc = glParm;
2453 checkGLcall("glAlphaFunc");
2455 break;
2457 case D3DRS_ALPHAREF :
2459 int glParm = This->alphafunc;
2460 float ref = 1.0f;
2462 ref = ((float) Value) / 255.0f;
2463 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2464 glAlphaFunc(glParm, ref);
2465 checkGLcall("glAlphaFunc");
2467 break;
2469 case D3DRS_CLIPPLANEENABLE :
2470 case D3DRS_CLIPPING :
2472 /* Ensure we only do the changed clip planes */
2473 DWORD enable = 0xFFFFFFFF;
2474 DWORD disable = 0x00000000;
2476 /* If enabling / disabling all */
2477 if (State == D3DRS_CLIPPING) {
2478 if (Value) {
2479 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2480 disable = 0x00;
2481 } else {
2482 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2483 enable = 0x00;
2485 } else {
2486 enable = Value & ~OldValue;
2487 disable = ~Value & OldValue;
2490 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2491 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2492 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2493 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2494 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2495 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2497 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2498 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2499 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2500 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2501 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2502 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2504 /** update clipping status */
2505 if (enable) {
2506 This->StateBlock->clip_status.ClipUnion = 0;
2507 This->StateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2508 } else {
2509 This->StateBlock->clip_status.ClipUnion = 0;
2510 This->StateBlock->clip_status.ClipIntersection = 0;
2513 break;
2515 case D3DRS_BLENDOP :
2517 int glParm = GL_FUNC_ADD;
2519 switch ((D3DBLENDOP) Value) {
2520 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2521 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2522 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2523 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2524 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2525 default:
2526 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2528 TRACE("glBlendEquation(%x)\n", glParm);
2529 glBlendEquation(glParm);
2530 checkGLcall("glBlendEquation");
2532 break;
2534 case D3DRS_TEXTUREFACTOR :
2536 unsigned int i;
2538 /* Note the texture color applies to all textures whereas
2539 GL_TEXTURE_ENV_COLOR applies to active only */
2540 float col[4];
2541 D3DCOLORTOGLFLOAT4(Value, col);
2542 /* Set the default alpha blend color */
2543 glBlendColor(col[0], col[1], col[2], col[3]);
2544 checkGLcall("glBlendColor");
2546 /* And now the default texture color as well */
2547 for (i = 0; i < GL_LIMITS(textures); i++) {
2549 /* Note the D3DRS value applies to all textures, but GL has one
2550 per texture, so apply it now ready to be used! */
2551 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2552 #if defined(GL_VERSION_1_3)
2553 glActiveTexture(GL_TEXTURE0 + i);
2554 #else
2555 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2556 #endif
2557 checkGLcall("Activate texture.. to update const color");
2558 } else if (i>0) {
2559 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2562 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2563 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2566 break;
2568 case D3DRS_SPECULARENABLE :
2570 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2571 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2572 specular color. This is wrong:
2573 Separate specular color means the specular colour is maintained separately, whereas
2574 single color means it is merged in. However in both cases they are being used to
2575 some extent.
2576 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2577 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2578 running 1.4 yet!
2580 if (Value) {
2581 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2582 checkGLcall("glMaterialfv");
2583 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2584 glEnable(GL_COLOR_SUM_EXT);
2585 } else {
2586 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2588 checkGLcall("glEnable(GL_COLOR_SUM)");
2589 } else {
2590 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2592 /* for the case of enabled lighting: */
2593 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2594 checkGLcall("glMaterialfv");
2596 /* for the case of disabled lighting: */
2597 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2598 glDisable(GL_COLOR_SUM_EXT);
2599 } else {
2600 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2602 checkGLcall("glDisable(GL_COLOR_SUM)");
2605 break;
2607 case D3DRS_STENCILENABLE :
2608 if (Value) {
2609 glEnable(GL_STENCIL_TEST);
2610 checkGLcall("glEnable GL_STENCIL_TEST");
2611 } else {
2612 glDisable(GL_STENCIL_TEST);
2613 checkGLcall("glDisable GL_STENCIL_TEST");
2615 break;
2617 case D3DRS_STENCILFUNC :
2619 int glParm = GL_ALWAYS;
2620 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2621 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2623 switch ((D3DCMPFUNC) Value) {
2624 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2625 case D3DCMP_LESS: glParm=GL_LESS; break;
2626 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2627 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2628 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2629 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2630 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2631 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2632 default:
2633 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2635 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2636 This->stencilfunc = glParm;
2637 glStencilFunc(glParm, ref, mask);
2638 checkGLcall("glStencilFunc");
2640 break;
2642 case D3DRS_STENCILREF :
2644 int glParm = This->stencilfunc;
2645 int ref = 0;
2646 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2648 ref = Value;
2649 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2650 glStencilFunc(glParm, ref, mask);
2651 checkGLcall("glStencilFunc");
2653 break;
2655 case D3DRS_STENCILMASK :
2657 int glParm = This->stencilfunc;
2658 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2659 GLuint mask = Value;
2661 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2662 glStencilFunc(glParm, ref, mask);
2663 checkGLcall("glStencilFunc");
2665 break;
2667 case D3DRS_STENCILFAIL :
2669 GLenum fail ;
2670 GLenum zpass ;
2671 GLenum zfail ;
2673 fail = StencilOp(Value);
2674 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2675 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2676 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2677 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2679 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2680 glStencilOp(fail, zfail, zpass);
2681 checkGLcall("glStencilOp(fail, zfail, zpass);");
2683 break;
2684 case D3DRS_STENCILZFAIL :
2686 GLenum fail ;
2687 GLenum zpass ;
2688 GLenum zfail ;
2690 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2691 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2692 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2693 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2694 zfail = StencilOp(Value);
2696 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2697 glStencilOp(fail, zfail, zpass);
2698 checkGLcall("glStencilOp(fail, zfail, zpass);");
2700 break;
2701 case D3DRS_STENCILPASS :
2703 GLenum fail ;
2704 GLenum zpass ;
2705 GLenum zfail ;
2707 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2708 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2709 zpass = StencilOp(Value);
2710 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2711 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2713 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2714 glStencilOp(fail, zfail, zpass);
2715 checkGLcall("glStencilOp(fail, zfail, zpass);");
2717 break;
2719 case D3DRS_STENCILWRITEMASK :
2721 glStencilMask(Value);
2722 TRACE("glStencilMask(%lu)\n", Value);
2723 checkGLcall("glStencilMask");
2725 break;
2727 case D3DRS_FOGENABLE :
2729 if (Value/* && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2730 glEnable(GL_FOG);
2731 checkGLcall("glEnable GL_FOG");
2732 } else {
2733 glDisable(GL_FOG);
2734 checkGLcall("glDisable GL_FOG");
2737 break;
2739 case D3DRS_RANGEFOGENABLE :
2741 if (Value) {
2742 TRACE("Enabled RANGEFOG");
2743 } else {
2744 TRACE("Disabled RANGEFOG");
2747 break;
2749 case D3DRS_FOGCOLOR :
2751 float col[4];
2752 D3DCOLORTOGLFLOAT4(Value, col);
2753 /* Set the default alpha blend color */
2754 glFogfv(GL_FOG_COLOR, &col[0]);
2755 checkGLcall("glFog GL_FOG_COLOR");
2757 break;
2759 case D3DRS_FOGTABLEMODE :
2761 glHint(GL_FOG_HINT, GL_NICEST);
2762 switch (Value) {
2763 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2764 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2765 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2766 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2767 default:
2768 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2770 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2771 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2774 break;
2776 case D3DRS_FOGVERTEXMODE :
2778 glHint(GL_FOG_HINT, GL_FASTEST);
2779 switch (Value) {
2780 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2781 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2782 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2783 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2784 default:
2785 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2787 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2788 glFogi(GL_FOG_DISTANCE_MODE_NV, This->StateBlock->renderstate[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2791 break;
2793 case D3DRS_FOGSTART :
2795 tmpvalue.d = Value;
2796 glFogfv(GL_FOG_START, &tmpvalue.f);
2797 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2798 TRACE("Fog Start == %f\n", tmpvalue.f);
2800 break;
2802 case D3DRS_FOGEND :
2804 tmpvalue.d = Value;
2805 glFogfv(GL_FOG_END, &tmpvalue.f);
2806 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2807 TRACE("Fog End == %f\n", tmpvalue.f);
2809 break;
2811 case D3DRS_FOGDENSITY :
2813 tmpvalue.d = Value;
2814 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2815 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2817 break;
2819 case D3DRS_VERTEXBLEND :
2821 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2822 TRACE("Vertex Blending state to %ld\n", Value);
2824 break;
2826 case D3DRS_TWEENFACTOR :
2828 tmpvalue.d = Value;
2829 This->UpdateStateBlock->tween_factor = tmpvalue.f;
2830 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2832 break;
2834 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2836 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2838 break;
2840 case D3DRS_COLORVERTEX :
2841 case D3DRS_DIFFUSEMATERIALSOURCE :
2842 case D3DRS_SPECULARMATERIALSOURCE :
2843 case D3DRS_AMBIENTMATERIALSOURCE :
2844 case D3DRS_EMISSIVEMATERIALSOURCE :
2846 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2848 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2849 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2850 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2851 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2852 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2853 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2855 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2856 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2857 Parm = GL_AMBIENT_AND_DIFFUSE;
2858 } else {
2859 Parm = GL_DIFFUSE;
2861 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2862 Parm = GL_AMBIENT;
2863 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2864 Parm = GL_EMISSION;
2865 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2866 Parm = GL_SPECULAR;
2867 } else {
2868 Parm = -1;
2871 if (Parm == -1) {
2872 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2873 } else {
2874 This->tracking_color = NEEDS_TRACKING;
2875 This->tracking_parm = Parm;
2878 } else {
2879 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2882 break;
2884 case D3DRS_LINEPATTERN :
2886 union {
2887 DWORD d;
2888 D3DLINEPATTERN lp;
2889 } tmppattern;
2890 tmppattern.d = Value;
2892 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2894 if (tmppattern.lp.wRepeatFactor) {
2895 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2896 checkGLcall("glLineStipple(repeat, linepattern)");
2897 glEnable(GL_LINE_STIPPLE);
2898 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2899 } else {
2900 glDisable(GL_LINE_STIPPLE);
2901 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2904 break;
2906 case D3DRS_ZBIAS :
2908 if (Value) {
2909 tmpvalue.d = Value;
2910 TRACE("ZBias value %f\n", tmpvalue.f);
2911 glPolygonOffset(0, -tmpvalue.f);
2912 checkGLcall("glPolygonOffset(0, -Value)");
2913 glEnable(GL_POLYGON_OFFSET_FILL);
2914 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2915 glEnable(GL_POLYGON_OFFSET_LINE);
2916 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2917 glEnable(GL_POLYGON_OFFSET_POINT);
2918 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2919 } else {
2920 glDisable(GL_POLYGON_OFFSET_FILL);
2921 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2922 glDisable(GL_POLYGON_OFFSET_LINE);
2923 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2924 glDisable(GL_POLYGON_OFFSET_POINT);
2925 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2928 break;
2930 case D3DRS_NORMALIZENORMALS :
2931 if (Value) {
2932 glEnable(GL_NORMALIZE);
2933 checkGLcall("glEnable(GL_NORMALIZE);");
2934 } else {
2935 glDisable(GL_NORMALIZE);
2936 checkGLcall("glDisable(GL_NORMALIZE);");
2938 break;
2940 case D3DRS_POINTSIZE :
2941 tmpvalue.d = Value;
2942 TRACE("Set point size to %f\n", tmpvalue.f);
2943 glPointSize(tmpvalue.f);
2944 checkGLcall("glPointSize(...);");
2945 break;
2947 case D3DRS_POINTSIZE_MIN :
2948 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2949 tmpvalue.d = Value;
2950 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2951 checkGLcall("glPointParameterfEXT(...);");
2952 } else {
2953 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2955 break;
2957 case D3DRS_POINTSIZE_MAX :
2958 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2959 tmpvalue.d = Value;
2960 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2961 checkGLcall("glPointParameterfEXT(...);");
2962 } else {
2963 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2965 break;
2967 case D3DRS_POINTSCALE_A :
2968 case D3DRS_POINTSCALE_B :
2969 case D3DRS_POINTSCALE_C :
2970 case D3DRS_POINTSCALEENABLE :
2972 /* If enabled, supply the parameters, otherwise fall back to defaults */
2973 if (This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2974 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2975 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]);
2976 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]);
2977 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]);
2979 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2980 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2981 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2982 } else {
2983 TRACE("D3DRS_POINTSCALEENABLE not supported on this opengl\n");
2985 } else {
2986 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2987 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2988 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2989 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...);");
2990 } else {
2991 TRACE("D3DRS_POINTSCALEENABLE not supported, but not on either\n");
2994 break;
2997 case D3DRS_COLORWRITEENABLE :
2999 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
3000 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
3001 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
3002 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
3003 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
3004 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
3005 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
3006 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
3007 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
3008 checkGLcall("glColorMask(...)");
3010 break;
3012 case D3DRS_LOCALVIEWER :
3014 GLint state = (Value) ? 1 : 0;
3015 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
3016 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
3018 break;
3020 case D3DRS_LASTPIXEL :
3022 if (Value) {
3023 TRACE("Last Pixel Drawing Enabled\n");
3024 } else {
3025 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
3028 break;
3030 case D3DRS_SOFTWAREVERTEXPROCESSING :
3032 if (Value) {
3033 TRACE("Software Processing Enabled\n");
3034 } else {
3035 TRACE("Software Processing Disabled\n");
3038 break;
3040 /** not supported */
3041 case D3DRS_ZVISIBLE :
3043 LEAVE_GL();
3044 return D3DERR_INVALIDCALL;
3047 /* Unhandled yet...! */
3048 case D3DRS_EDGEANTIALIAS :
3049 case D3DRS_WRAP0 :
3050 case D3DRS_WRAP1 :
3051 case D3DRS_WRAP2 :
3052 case D3DRS_WRAP3 :
3053 case D3DRS_WRAP4 :
3054 case D3DRS_WRAP5 :
3055 case D3DRS_WRAP6 :
3056 case D3DRS_WRAP7 :
3057 case D3DRS_POINTSPRITEENABLE :
3058 case D3DRS_MULTISAMPLEANTIALIAS :
3059 case D3DRS_MULTISAMPLEMASK :
3060 case D3DRS_PATCHEDGESTYLE :
3061 case D3DRS_PATCHSEGMENTS :
3062 case D3DRS_DEBUGMONITORTOKEN :
3063 case D3DRS_POSITIONORDER :
3064 case D3DRS_NORMALORDER :
3065 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
3066 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
3067 break;
3068 default:
3069 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
3072 LEAVE_GL();
3074 return D3D_OK;
3076 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
3077 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3078 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
3079 *pValue = This->StateBlock->renderstate[State];
3080 return D3D_OK;
3082 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
3083 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3085 TRACE("(%p)\n", This);
3087 return IDirect3DDeviceImpl_BeginStateBlock(This);
3089 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
3090 IDirect3DStateBlockImpl* pSB;
3091 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3092 HRESULT res;
3094 TRACE("(%p)\n", This);
3096 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
3097 *pToken = (DWORD) pSB;
3098 return res;
3101 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3102 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3103 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3105 TRACE("(%p)\n", This);
3107 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
3110 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3111 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3112 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3114 TRACE("(%p)\n", This);
3116 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
3118 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
3119 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
3120 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3122 TRACE("(%p)\n", This);
3124 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
3127 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
3128 IDirect3DStateBlockImpl* pSB;
3129 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3130 HRESULT res;
3132 TRACE("(%p) : for type %d\n", This, Type);
3134 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
3135 *pToken = (DWORD) pSB;
3136 return res;
3139 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
3140 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3141 FIXME("(%p) : stub\n", This);
3142 if (NULL == pClipStatus) {
3143 return D3DERR_INVALIDCALL;
3145 This->UpdateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
3146 This->UpdateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
3147 return D3D_OK;
3149 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
3150 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3151 FIXME("(%p) : stub\n", This);
3152 if (NULL == pClipStatus) {
3153 return D3DERR_INVALIDCALL;
3155 pClipStatus->ClipUnion = This->UpdateStateBlock->clip_status.ClipUnion;
3156 pClipStatus->ClipIntersection = This->UpdateStateBlock->clip_status.ClipIntersection;
3157 return D3D_OK;
3159 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
3160 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3161 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
3162 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
3163 if (*ppTexture)
3164 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
3165 return D3D_OK;
3167 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
3169 IDirect3DBaseTexture8 *oldTxt;
3170 BOOL reapplyStates = TRUE;
3171 INT oldTextureDimensions = -1;
3172 DWORD reapplyFlags = 0;
3174 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3175 D3DRESOURCETYPE textureType;
3177 oldTxt = This->UpdateStateBlock->textures[Stage];
3178 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
3180 /* Reject invalid texture units */
3181 if (Stage >= GL_LIMITS(textures)) {
3182 TRACE("Attempt to access invalid texture rejected\n");
3183 return D3DERR_INVALIDCALL;
3186 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
3187 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
3188 This->UpdateStateBlock->textures[Stage] = pTexture;
3190 /* Handle recording of state blocks */
3191 if (This->isRecordingState) {
3192 TRACE("Recording... not performing anything\n");
3193 return D3D_OK;
3196 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
3197 ENTER_GL();
3199 /* Make appropriate texture active */
3200 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3201 #if defined(GL_VERSION_1_3)
3202 glActiveTexture(GL_TEXTURE0 + Stage);
3203 checkGLcall("glActiveTexture");
3204 #else
3205 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3206 checkGLcall("glActiveTextureARB");
3207 #endif
3208 } else if (Stage>0) {
3209 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3212 /* Decrement the count of the previous texture */
3213 if (NULL != oldTxt) {
3214 IDirect3DBaseTexture8Impl_Release(oldTxt);
3217 if (NULL != pTexture) {
3218 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3220 /* Now setup the texture appropraitly */
3221 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3223 if (textureType == D3DRTYPE_TEXTURE) {
3224 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3225 TRACE("Skipping setting texture as old == new\n");
3226 reapplyStates = FALSE;
3227 } else {
3228 /* Standard 2D texture */
3229 TRACE("Standard 2d texture\n");
3230 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3232 /* Load up the texture now */
3233 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3235 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3236 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3237 TRACE("Skipping setting texture as old == new\n");
3238 reapplyStates = FALSE;
3239 } else {
3240 /* Standard 3D (volume) texture */
3241 TRACE("Standard 3d texture\n");
3242 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3244 /* Load up the texture now */
3245 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3247 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3248 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3249 TRACE("Skipping setting texture as old == new\n");
3250 reapplyStates = FALSE;
3251 } else {
3252 /* Standard Cube texture */
3253 TRACE("Standard Cube texture\n");
3254 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3256 /* Load up the texture now */
3257 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3259 } else {
3260 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3262 } else {
3263 TRACE("Setting to no texture (ie default texture)\n");
3264 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3265 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3266 checkGLcall("glBindTexture");
3267 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3270 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3271 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3272 glDisable(oldTextureDimensions);
3273 checkGLcall("Disable oldTextureDimensions");
3274 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3275 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3276 checkGLcall("glEnable new texture dimensions");
3279 /* If Alpha arg1 is texture then handle the special case when there changes between a
3280 texture and no texture - See comments in set_tex_op */
3281 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3282 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3284 reapplyFlags |= REAPPLY_ALPHAOP;
3289 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3290 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3291 if (reapplyStates) {
3292 setupTextureStates(iface, Stage, reapplyFlags);
3295 LEAVE_GL();
3297 return D3D_OK;
3300 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3301 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3302 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3303 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3304 return D3D_OK;
3307 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3308 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3309 union {
3310 float f;
3311 DWORD d;
3312 } tmpvalue;
3314 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3316 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3318 /* Reject invalid texture units */
3319 if (Stage >= GL_LIMITS(textures)) {
3320 TRACE("Attempt to access invalid texture rejected\n");
3321 return D3DERR_INVALIDCALL;
3324 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3325 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3326 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3328 /* Handle recording of state blocks */
3329 if (This->isRecordingState) {
3330 TRACE("Recording... not performing anything\n");
3331 return D3D_OK;
3334 ENTER_GL();
3336 /* Make appropriate texture active */
3337 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3338 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3339 #if defined(GL_VERSION_1_3)
3340 glActiveTexture(GL_TEXTURE0 + Stage);
3341 vcheckGLcall("glActiveTexture");
3342 #else
3343 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3344 vcheckGLcall("glActiveTextureARB");
3345 #endif
3346 } else if (Stage > 0) {
3347 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3350 switch (Type) {
3352 case D3DTSS_MINFILTER :
3353 case D3DTSS_MIPFILTER :
3355 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3356 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3357 GLint realVal = GL_LINEAR;
3359 if (ValueMIN == D3DTEXF_NONE) {
3360 /* Doesn't really make sense - Windows just seems to disable
3361 mipmapping when this occurs */
3362 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3363 realVal = GL_LINEAR;
3364 } else if (ValueMIN == D3DTEXF_POINT) {
3365 /* GL_NEAREST_* */
3366 if (ValueMIP == D3DTEXF_NONE) {
3367 realVal = GL_NEAREST;
3368 } else if (ValueMIP == D3DTEXF_POINT) {
3369 realVal = GL_NEAREST_MIPMAP_NEAREST;
3370 } else if (ValueMIP == D3DTEXF_LINEAR) {
3371 realVal = GL_NEAREST_MIPMAP_LINEAR;
3372 } else {
3373 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3374 realVal = GL_NEAREST;
3376 } else if (ValueMIN == D3DTEXF_LINEAR) {
3377 /* GL_LINEAR_* */
3378 if (ValueMIP == D3DTEXF_NONE) {
3379 realVal = GL_LINEAR;
3380 } else if (ValueMIP == D3DTEXF_POINT) {
3381 realVal = GL_LINEAR_MIPMAP_NEAREST;
3382 } else if (ValueMIP == D3DTEXF_LINEAR) {
3383 realVal = GL_LINEAR_MIPMAP_LINEAR;
3384 } else {
3385 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3386 realVal = GL_LINEAR;
3388 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3389 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3390 if (ValueMIP == D3DTEXF_NONE) {
3391 realVal = GL_LINEAR_MIPMAP_LINEAR;
3392 } else if (ValueMIP == D3DTEXF_POINT) {
3393 realVal = GL_LINEAR_MIPMAP_NEAREST;
3394 } else if (ValueMIP == D3DTEXF_LINEAR) {
3395 realVal = GL_LINEAR_MIPMAP_LINEAR;
3396 } else {
3397 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3398 realVal = GL_LINEAR;
3400 } else {
3401 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3402 realVal = GL_LINEAR;
3404 } else {
3405 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3406 realVal = GL_LINEAR_MIPMAP_LINEAR;
3409 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3410 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3411 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3413 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3415 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3416 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3417 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3418 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3419 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3422 break;
3424 case D3DTSS_MAGFILTER :
3426 DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3427 GLint realVal = GL_NEAREST;
3429 if (ValueMAG == D3DTEXF_POINT) {
3430 realVal = GL_NEAREST;
3431 } else if (ValueMAG == D3DTEXF_LINEAR) {
3432 realVal = GL_LINEAR;
3433 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3434 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3435 realVal = GL_LINEAR;
3436 } else {
3437 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3438 realVal = GL_NEAREST;
3440 } else {
3441 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3442 realVal = GL_NEAREST;
3444 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3445 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3446 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3448 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3450 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3451 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3452 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3453 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3454 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3457 break;
3459 case D3DTSS_MAXMIPLEVEL :
3462 * Not really the same, but the more apprioprate than nothing
3464 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3465 GL_TEXTURE_BASE_LEVEL,
3466 This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3467 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3469 break;
3471 case D3DTSS_MAXANISOTROPY :
3473 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3474 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3475 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3476 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3477 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3480 break;
3482 case D3DTSS_MIPMAPLODBIAS :
3484 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3485 tmpvalue.d = Value;
3486 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3487 GL_TEXTURE_LOD_BIAS_EXT,
3488 tmpvalue.f);
3489 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3492 break;
3494 case D3DTSS_ALPHAOP :
3495 case D3DTSS_COLOROP :
3498 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3499 /* TODO: Disable by making this and all later levels disabled */
3500 glDisable(GL_TEXTURE_1D);
3501 checkGLcall("Disable GL_TEXTURE_1D");
3502 glDisable(GL_TEXTURE_2D);
3503 checkGLcall("Disable GL_TEXTURE_2D");
3504 glDisable(GL_TEXTURE_3D);
3505 checkGLcall("Disable GL_TEXTURE_3D");
3506 break; /* Don't bother setting the texture operations */
3507 } else {
3508 /* Enable only the appropriate texture dimension */
3509 if (Type == D3DTSS_COLOROP) {
3510 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3511 glEnable(GL_TEXTURE_1D);
3512 checkGLcall("Enable GL_TEXTURE_1D");
3513 } else {
3514 glDisable(GL_TEXTURE_1D);
3515 checkGLcall("Disable GL_TEXTURE_1D");
3517 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3518 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3519 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3520 checkGLcall("Enable GL_TEXTURE_2D");
3521 } else {
3522 glEnable(GL_TEXTURE_2D);
3523 checkGLcall("Enable GL_TEXTURE_2D");
3525 } else {
3526 glDisable(GL_TEXTURE_2D);
3527 checkGLcall("Disable GL_TEXTURE_2D");
3529 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3530 glEnable(GL_TEXTURE_3D);
3531 checkGLcall("Enable GL_TEXTURE_3D");
3532 } else {
3533 glDisable(GL_TEXTURE_3D);
3534 checkGLcall("Disable GL_TEXTURE_3D");
3536 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3537 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3538 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3539 } else {
3540 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3541 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3545 /* Drop through... (Except disable case) */
3546 case D3DTSS_COLORARG0 :
3547 case D3DTSS_COLORARG1 :
3548 case D3DTSS_COLORARG2 :
3549 case D3DTSS_ALPHAARG0 :
3550 case D3DTSS_ALPHAARG1 :
3551 case D3DTSS_ALPHAARG2 :
3553 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3554 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3555 if (isAlphaArg) {
3556 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3557 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3558 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3559 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3560 } else {
3561 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3562 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3563 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3564 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3567 break;
3570 case D3DTSS_ADDRESSU :
3571 case D3DTSS_ADDRESSV :
3572 case D3DTSS_ADDRESSW :
3574 GLint wrapParm = GL_REPEAT;
3576 switch (Value) {
3577 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3578 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3579 case D3DTADDRESS_BORDER:
3581 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3582 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3583 } else {
3584 /* FIXME: Not right, but better */
3585 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3586 wrapParm = GL_REPEAT;
3589 break;
3590 case D3DTADDRESS_MIRROR:
3592 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3593 wrapParm = GL_MIRRORED_REPEAT_ARB;
3594 } else {
3595 /* Unsupported in OpenGL pre-1.4 */
3596 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3597 wrapParm = GL_REPEAT;
3600 break;
3601 case D3DTADDRESS_MIRRORONCE:
3603 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3604 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3605 } else {
3606 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3607 wrapParm = GL_REPEAT;
3610 break;
3612 default:
3613 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3614 wrapParm = GL_REPEAT;
3617 switch (Type) {
3618 case D3DTSS_ADDRESSU:
3619 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3620 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3621 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3622 break;
3623 case D3DTSS_ADDRESSV:
3624 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3625 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3626 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3627 break;
3628 case D3DTSS_ADDRESSW:
3629 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3630 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3631 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3632 break;
3633 default: /* nop */
3634 break; /** stupic compilator */
3637 break;
3639 case D3DTSS_BORDERCOLOR :
3641 float col[4];
3642 D3DCOLORTOGLFLOAT4(Value, col);
3643 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3644 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3645 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3647 break;
3649 case D3DTSS_TEXCOORDINDEX :
3651 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3653 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3654 one flag, you can still specify an index value, which the system uses to
3655 determine the texture wrapping mode.
3656 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3657 means use the vertex position (camera-space) as the input texture coordinates
3658 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3659 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3660 to the TEXCOORDINDEX value */
3662 /**
3663 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3665 switch (Value & 0xFFFF0000) {
3666 case D3DTSS_TCI_PASSTHRU:
3667 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3668 glDisable(GL_TEXTURE_GEN_S);
3669 glDisable(GL_TEXTURE_GEN_T);
3670 glDisable(GL_TEXTURE_GEN_R);
3671 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3672 break;
3674 case D3DTSS_TCI_CAMERASPACEPOSITION:
3675 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3676 as the input texture coordinates for this stage's texture transformation. This
3677 equates roughly to EYE_LINEAR */
3679 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3680 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3681 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3682 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3683 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3685 glMatrixMode(GL_MODELVIEW);
3686 glPushMatrix();
3687 glLoadIdentity();
3688 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3689 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3690 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3691 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3692 glPopMatrix();
3694 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3695 glEnable(GL_TEXTURE_GEN_S);
3696 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3697 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3698 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3699 glEnable(GL_TEXTURE_GEN_T);
3700 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3701 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3702 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3703 glEnable(GL_TEXTURE_GEN_R);
3704 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3705 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3706 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3708 break;
3710 case D3DTSS_TCI_CAMERASPACENORMAL:
3712 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3713 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3714 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3715 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3716 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3717 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3719 glMatrixMode(GL_MODELVIEW);
3720 glPushMatrix();
3721 glLoadIdentity();
3722 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3723 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3724 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3725 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3726 glPopMatrix();
3728 glEnable(GL_TEXTURE_GEN_S);
3729 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3730 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3731 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3732 glEnable(GL_TEXTURE_GEN_T);
3733 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3734 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3735 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3736 glEnable(GL_TEXTURE_GEN_R);
3737 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3738 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3739 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3742 break;
3744 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3746 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3747 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3748 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3749 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3750 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3751 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3753 glMatrixMode(GL_MODELVIEW);
3754 glPushMatrix();
3755 glLoadIdentity();
3756 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3757 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3758 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3759 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3760 glPopMatrix();
3762 glEnable(GL_TEXTURE_GEN_S);
3763 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3764 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3765 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3766 glEnable(GL_TEXTURE_GEN_T);
3767 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3768 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3769 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3770 glEnable(GL_TEXTURE_GEN_R);
3771 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3772 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3773 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3776 break;
3778 /* Unhandled types: */
3779 default:
3780 /* Todo: */
3781 /* ? disable GL_TEXTURE_GEN_n ? */
3782 glDisable(GL_TEXTURE_GEN_S);
3783 glDisable(GL_TEXTURE_GEN_T);
3784 glDisable(GL_TEXTURE_GEN_R);
3785 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3786 break;
3789 break;
3791 /* Unhandled */
3792 case D3DTSS_TEXTURETRANSFORMFLAGS :
3793 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3794 break;
3796 case D3DTSS_BUMPENVMAT00 :
3797 case D3DTSS_BUMPENVMAT01 :
3798 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3799 break;
3800 case D3DTSS_BUMPENVMAT10 :
3801 case D3DTSS_BUMPENVMAT11 :
3802 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3803 break;
3805 case D3DTSS_BUMPENVLSCALE :
3806 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3807 break;
3809 case D3DTSS_BUMPENVLOFFSET :
3810 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3811 break;
3813 case D3DTSS_RESULTARG :
3814 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3815 break;
3817 default:
3818 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3819 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3822 LEAVE_GL();
3824 return D3D_OK;
3826 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3827 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3828 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3829 return D3D_OK;
3831 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3832 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3833 FIXME("(%p) : stub\n", This);
3834 return D3D_OK;
3836 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3837 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3838 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3839 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3840 if (PaletteNumber >= MAX_PALETTES) {
3841 return D3DERR_INVALIDCALL;
3843 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3844 return D3D_OK;
3846 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3847 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3848 if (PaletteNumber >= MAX_PALETTES) {
3849 return D3DERR_INVALIDCALL;
3851 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3852 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3853 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3854 return D3D_OK;
3856 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3857 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3858 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3859 if (PaletteNumber >= MAX_PALETTES) {
3860 return D3DERR_INVALIDCALL;
3862 This->currentPalette = PaletteNumber;
3864 #if defined(GL_EXT_paletted_texture)
3865 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3867 ENTER_GL();
3869 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3870 GL_RGBA, /* internal format */
3871 256, /* table size */
3872 GL_RGBA, /* table format */
3873 GL_UNSIGNED_BYTE, /* table type */
3874 This->palettes[PaletteNumber]);
3875 checkGLcall("glColorTableEXT");
3877 LEAVE_GL();
3879 } else {
3880 /* Delayed palette handling ... waiting for software emulation into preload code */
3882 #endif
3883 return D3D_OK;
3885 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3886 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3887 *PaletteNumber = This->currentPalette;
3888 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3889 return D3D_OK;
3891 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3893 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3894 This->StateBlock->streamIsUP = FALSE;
3896 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3897 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3899 return D3D_OK;
3901 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3902 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3903 UINT idxStride = 2;
3904 IDirect3DIndexBuffer8 *pIB;
3905 D3DINDEXBUFFER_DESC IdxBufDsc;
3907 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3908 pIB = This->StateBlock->pIndexData;
3909 This->StateBlock->streamIsUP = FALSE;
3911 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d \n", This,
3912 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3913 minIndex, NumVertices, startIndex, primCount);
3915 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3916 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3917 idxStride = 2;
3918 } else {
3919 idxStride = 4;
3922 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3923 minIndex);
3925 return D3D_OK;
3927 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3928 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3930 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3931 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3933 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3935 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3936 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3937 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3938 This->StateBlock->streamIsUP = TRUE;
3939 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3940 This->StateBlock->stream_stride[0] = 0;
3941 This->StateBlock->stream_source[0] = NULL;
3943 /*stream zero settings set to null at end */
3944 return D3D_OK;
3946 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3947 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3948 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3949 UINT VertexStreamZeroStride) {
3950 int idxStride;
3951 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3952 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),
3953 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3955 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3956 if (IndexDataFormat == D3DFMT_INDEX16) {
3957 idxStride = 2;
3958 } else {
3959 idxStride = 4;
3962 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3963 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3964 This->StateBlock->streamIsUP = TRUE;
3965 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3966 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3968 /*stream zero settings set to null at end */
3969 This->StateBlock->stream_source[0] = NULL;
3970 This->StateBlock->stream_stride[0] = 0;
3971 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3973 return D3D_OK;
3975 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3976 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3977 FIXME("(%p) : stub\n", This); return D3D_OK;
3979 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3980 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3981 IDirect3DVertexShaderImpl* object;
3982 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3983 HRESULT res;
3984 UINT i;
3986 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3987 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3988 return D3DERR_INVALIDCALL;
3990 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3991 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3992 return D3DERR_OUTOFVIDEOMEMORY;
3995 /** Create the Vertex Shader */
3996 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3997 /** TODO: check FAILED(res) */
3999 /** Create and Bind the Vertex Shader Declaration */
4000 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
4001 /** TODO: check FAILED(res) */
4003 VertexShaders[i] = object;
4004 VertexShaderDeclarations[i] = attached_decl;
4005 *pHandle = VS_HIGHESTFIXEDFXF + i;
4006 TRACE("Finished creating vertex shader %lx\n", *pHandle);
4008 return D3D_OK;
4010 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4011 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4013 This->UpdateStateBlock->VertexShader = Handle;
4014 This->UpdateStateBlock->Changed.vertexShader = TRUE;
4015 This->UpdateStateBlock->Set.vertexShader = TRUE;
4017 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
4018 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
4019 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
4020 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4021 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4022 } else { /* use a fvf, so desactivate the vshader decl */
4023 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
4024 This->UpdateStateBlock->vertexShaderDecl = NULL;
4025 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
4026 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
4028 /* Handle recording of state blocks */
4029 if (This->isRecordingState) {
4030 TRACE("Recording... not performing anything\n");
4031 return D3D_OK;
4034 * TODO: merge HAL shaders context switching from prototype
4036 return D3D_OK;
4038 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4039 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4040 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
4041 *pHandle = This->StateBlock->VertexShader;
4042 return D3D_OK;
4045 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4046 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4047 IDirect3DVertexShaderImpl* object;
4048 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4050 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4051 return D3DERR_INVALIDCALL;
4055 * Delete Vertex Shader
4057 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
4058 if (NULL == object) {
4059 return D3DERR_INVALIDCALL;
4061 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
4062 /* TODO: check validity of object */
4063 HeapFree(GetProcessHeap(), 0, (void *)object->function);
4064 if (object->prgId != 0) {
4065 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4067 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4068 HeapFree(GetProcessHeap(), 0, (void *)object);
4069 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4072 * Delete Vertex Shader Declaration
4074 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
4075 if (NULL == attached_decl) {
4076 return D3DERR_INVALIDCALL;
4078 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
4079 /* TODO: check validity of object */
4080 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
4081 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
4082 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4084 return D3D_OK;
4087 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4088 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4090 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4091 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
4092 return D3DERR_INVALIDCALL;
4094 if (NULL == pConstantData) {
4095 return D3DERR_INVALIDCALL;
4097 if (ConstantCount > 1) {
4098 const FLOAT* f = (const FLOAT*)pConstantData;
4099 UINT i;
4100 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4101 for (i = 0; i < ConstantCount; ++i) {
4102 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4103 f += 4;
4105 } else {
4106 const FLOAT* f = (const FLOAT*) pConstantData;
4107 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4109 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
4110 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4111 return D3D_OK;
4113 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4114 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4116 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4117 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
4118 return D3DERR_INVALIDCALL;
4120 if (NULL == pConstantData) {
4121 return D3DERR_INVALIDCALL;
4123 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4124 return D3D_OK;
4126 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4127 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4128 IDirect3DVertexShaderDeclarationImpl* attached_decl;
4130 attached_decl = VERTEX_SHADER_DECL(Handle);
4131 if (NULL == attached_decl) {
4132 return D3DERR_INVALIDCALL;
4134 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
4136 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4137 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
4138 IDirect3DVertexShaderImpl* object;
4140 object = VERTEX_SHADER(Handle);
4141 if (NULL == object) {
4142 return D3DERR_INVALIDCALL;
4144 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4147 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
4148 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4149 IDirect3DIndexBuffer8 *oldIdxs;
4151 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
4152 oldIdxs = This->StateBlock->pIndexData;
4154 This->UpdateStateBlock->Changed.Indices = TRUE;
4155 This->UpdateStateBlock->Set.Indices = TRUE;
4156 This->UpdateStateBlock->pIndexData = pIndexData;
4157 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
4159 /* Handle recording of state blocks */
4160 if (This->isRecordingState) {
4161 TRACE("Recording... not performing anything\n");
4162 return D3D_OK;
4165 if (oldIdxs) IDirect3DIndexBuffer8Impl_Release(oldIdxs);
4166 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRef(This->StateBlock->pIndexData);
4167 return D3D_OK;
4169 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
4170 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4171 FIXME("(%p) : stub\n", This);
4173 *ppIndexData = This->StateBlock->pIndexData;
4174 /* up ref count on ppindexdata */
4175 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
4176 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
4178 return D3D_OK;
4180 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
4181 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4182 IDirect3DPixelShaderImpl* object;
4183 HRESULT res;
4184 UINT i;
4186 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
4187 if (NULL == pFunction || NULL == pHandle) {
4188 return D3DERR_INVALIDCALL;
4190 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
4191 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
4192 return D3DERR_OUTOFVIDEOMEMORY;
4195 /** Create the Pixel Shader */
4196 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
4197 if (SUCCEEDED(res)) {
4198 PixelShaders[i] = object;
4199 *pHandle = VS_HIGHESTFIXEDFXF + i;
4200 return D3D_OK;
4202 *pHandle = 0xFFFFFFFF;
4203 return res;
4206 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4207 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4209 This->UpdateStateBlock->PixelShader = Handle;
4210 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4211 This->UpdateStateBlock->Set.pixelShader = TRUE;
4213 /* Handle recording of state blocks */
4214 if (This->isRecordingState) {
4215 TRACE_(d3d_shader)("Recording... not performing anything\n");
4216 return D3D_OK;
4219 if (Handle != 0) {
4220 TRACE_(d3d_shader)("(%p) : Set pixel shader with handle %lx\n", This, Handle);
4221 } else {
4222 TRACE_(d3d_shader)("(%p) : Remove pixel shader\n", This);
4225 return D3D_OK;
4228 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4229 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4230 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4231 *pHandle = This->StateBlock->PixelShader;
4232 return D3D_OK;
4235 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4236 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4237 IDirect3DPixelShaderImpl* object;
4239 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4240 return D3DERR_INVALIDCALL;
4242 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4243 if (NULL == object) {
4244 return D3DERR_INVALIDCALL;
4246 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4247 /* TODO: check validity of object before free */
4248 HeapFree(GetProcessHeap(), 0, (void *)object->function);
4249 if (object->prgId != 0) {
4250 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4252 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4253 HeapFree(GetProcessHeap(), 0, (void *)object);
4254 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4256 return D3D_OK;
4259 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4260 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4262 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4263 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4264 return D3DERR_INVALIDCALL;
4266 if (NULL == pConstantData) {
4267 return D3DERR_INVALIDCALL;
4269 if (ConstantCount > 1) {
4270 const FLOAT* f = (const FLOAT*)pConstantData;
4271 UINT i;
4272 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4273 for (i = 0; i < ConstantCount; ++i) {
4274 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4275 f += 4;
4277 } else {
4278 const FLOAT* f = (const FLOAT*) pConstantData;
4279 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4281 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4282 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4283 return D3D_OK;
4285 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4286 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4288 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4289 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4290 return D3DERR_INVALIDCALL;
4292 if (NULL == pConstantData) {
4293 return D3DERR_INVALIDCALL;
4295 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4296 return D3D_OK;
4298 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4299 IDirect3DPixelShaderImpl* object;
4301 object = PIXEL_SHADER(Handle);
4302 if (NULL == object) {
4303 return D3DERR_INVALIDCALL;
4305 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4307 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4308 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4309 FIXME("(%p) : stub\n", This); return D3D_OK;
4311 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4312 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4313 FIXME("(%p) : stub\n", This); return D3D_OK;
4315 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4316 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4317 FIXME("(%p) : stub\n", This); return D3D_OK;
4320 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4321 IDirect3DVertexBuffer8 *oldSrc;
4322 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4324 oldSrc = This->StateBlock->stream_source[StreamNumber];
4325 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4327 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4328 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4329 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4330 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4332 /* Handle recording of state blocks */
4333 if (This->isRecordingState) {
4334 TRACE("Recording... not performing anything\n");
4335 return D3D_OK;
4338 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_Release(oldSrc);
4339 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRef(pStreamData);
4340 return D3D_OK;
4342 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4343 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4344 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4345 *pStream = This->StateBlock->stream_source[StreamNumber];
4346 *pStride = This->StateBlock->stream_stride[StreamNumber];
4347 if (*pStream != NULL) IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4348 return D3D_OK;
4352 const IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
4354 IDirect3DDevice8Impl_QueryInterface,
4355 IDirect3DDevice8Impl_AddRef,
4356 IDirect3DDevice8Impl_Release,
4357 IDirect3DDevice8Impl_TestCooperativeLevel,
4358 IDirect3DDevice8Impl_GetAvailableTextureMem,
4359 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4360 IDirect3DDevice8Impl_GetDirect3D,
4361 IDirect3DDevice8Impl_GetDeviceCaps,
4362 IDirect3DDevice8Impl_GetDisplayMode,
4363 IDirect3DDevice8Impl_GetCreationParameters,
4364 IDirect3DDevice8Impl_SetCursorProperties,
4365 IDirect3DDevice8Impl_SetCursorPosition,
4366 IDirect3DDevice8Impl_ShowCursor,
4367 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4368 IDirect3DDevice8Impl_Reset,
4369 IDirect3DDevice8Impl_Present,
4370 IDirect3DDevice8Impl_GetBackBuffer,
4371 IDirect3DDevice8Impl_GetRasterStatus,
4372 IDirect3DDevice8Impl_SetGammaRamp,
4373 IDirect3DDevice8Impl_GetGammaRamp,
4374 IDirect3DDevice8Impl_CreateTexture,
4375 IDirect3DDevice8Impl_CreateVolumeTexture,
4376 IDirect3DDevice8Impl_CreateCubeTexture,
4377 IDirect3DDevice8Impl_CreateVertexBuffer,
4378 IDirect3DDevice8Impl_CreateIndexBuffer,
4379 IDirect3DDevice8Impl_CreateRenderTarget,
4380 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4381 IDirect3DDevice8Impl_CreateImageSurface,
4382 IDirect3DDevice8Impl_CopyRects,
4383 IDirect3DDevice8Impl_UpdateTexture,
4384 IDirect3DDevice8Impl_GetFrontBuffer,
4385 IDirect3DDevice8Impl_SetRenderTarget,
4386 IDirect3DDevice8Impl_GetRenderTarget,
4387 IDirect3DDevice8Impl_GetDepthStencilSurface,
4388 IDirect3DDevice8Impl_BeginScene,
4389 IDirect3DDevice8Impl_EndScene,
4390 IDirect3DDevice8Impl_Clear,
4391 IDirect3DDevice8Impl_SetTransform,
4392 IDirect3DDevice8Impl_GetTransform,
4393 IDirect3DDevice8Impl_MultiplyTransform,
4394 IDirect3DDevice8Impl_SetViewport,
4395 IDirect3DDevice8Impl_GetViewport,
4396 IDirect3DDevice8Impl_SetMaterial,
4397 IDirect3DDevice8Impl_GetMaterial,
4398 IDirect3DDevice8Impl_SetLight,
4399 IDirect3DDevice8Impl_GetLight,
4400 IDirect3DDevice8Impl_LightEnable,
4401 IDirect3DDevice8Impl_GetLightEnable,
4402 IDirect3DDevice8Impl_SetClipPlane,
4403 IDirect3DDevice8Impl_GetClipPlane,
4404 IDirect3DDevice8Impl_SetRenderState,
4405 IDirect3DDevice8Impl_GetRenderState,
4406 IDirect3DDevice8Impl_BeginStateBlock,
4407 IDirect3DDevice8Impl_EndStateBlock,
4408 IDirect3DDevice8Impl_ApplyStateBlock,
4409 IDirect3DDevice8Impl_CaptureStateBlock,
4410 IDirect3DDevice8Impl_DeleteStateBlock,
4411 IDirect3DDevice8Impl_CreateStateBlock,
4412 IDirect3DDevice8Impl_SetClipStatus,
4413 IDirect3DDevice8Impl_GetClipStatus,
4414 IDirect3DDevice8Impl_GetTexture,
4415 IDirect3DDevice8Impl_SetTexture,
4416 IDirect3DDevice8Impl_GetTextureStageState,
4417 IDirect3DDevice8Impl_SetTextureStageState,
4418 IDirect3DDevice8Impl_ValidateDevice,
4419 IDirect3DDevice8Impl_GetInfo,
4420 IDirect3DDevice8Impl_SetPaletteEntries,
4421 IDirect3DDevice8Impl_GetPaletteEntries,
4422 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4423 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4424 IDirect3DDevice8Impl_DrawPrimitive,
4425 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4426 IDirect3DDevice8Impl_DrawPrimitiveUP,
4427 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4428 IDirect3DDevice8Impl_ProcessVertices,
4429 IDirect3DDevice8Impl_CreateVertexShader,
4430 IDirect3DDevice8Impl_SetVertexShader,
4431 IDirect3DDevice8Impl_GetVertexShader,
4432 IDirect3DDevice8Impl_DeleteVertexShader,
4433 IDirect3DDevice8Impl_SetVertexShaderConstant,
4434 IDirect3DDevice8Impl_GetVertexShaderConstant,
4435 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4436 IDirect3DDevice8Impl_GetVertexShaderFunction,
4437 IDirect3DDevice8Impl_SetStreamSource,
4438 IDirect3DDevice8Impl_GetStreamSource,
4439 IDirect3DDevice8Impl_SetIndices,
4440 IDirect3DDevice8Impl_GetIndices,
4441 IDirect3DDevice8Impl_CreatePixelShader,
4442 IDirect3DDevice8Impl_SetPixelShader,
4443 IDirect3DDevice8Impl_GetPixelShader,
4444 IDirect3DDevice8Impl_DeletePixelShader,
4445 IDirect3DDevice8Impl_SetPixelShaderConstant,
4446 IDirect3DDevice8Impl_GetPixelShaderConstant,
4447 IDirect3DDevice8Impl_GetPixelShaderFunction,
4448 IDirect3DDevice8Impl_DrawRectPatch,
4449 IDirect3DDevice8Impl_DrawTriPatch,
4450 IDirect3DDevice8Impl_DeletePatch
4453 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4455 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4456 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4458 ENTER_GL();
4460 #if 0
4461 if (This->glCtx != This->render_ctx) {
4462 glXDestroyContext(This->display, This->render_ctx);
4463 This->render_ctx = This->glCtx;
4465 #endif
4466 if (This->win != This->drawable) {
4467 glXDestroyPbuffer(This->display, This->drawable);
4468 This->drawable = This->win;
4471 LEAVE_GL();
4473 #endif
4474 return D3D_OK;
4477 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4478 IDirect3DSurface8* RenderSurface,
4479 IDirect3DSurface8* StencilSurface) {
4481 HRESULT ret = D3DERR_INVALIDCALL;
4483 * Currently only active for GLX >= 1.3
4484 * for others versions we'll have to use GLXPixmaps
4486 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4487 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4488 * so only check OpenGL version
4490 #if defined(GL_VERSION_1_3)
4491 GLXFBConfig* cfgs = NULL;
4492 int nCfgs = 0;
4493 int attribs[256];
4494 int nAttribs = 0;
4495 D3DFORMAT BackBufferFormat = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Format;
4496 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? ((IDirect3DSurface8Impl*) StencilSurface)->myDesc.Format : 0;
4497 UINT Width = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Width;
4498 UINT Height = ((IDirect3DSurface8Impl*) RenderSurface)->myDesc.Height;
4499 IDirect3DSurface8Impl* tmp;
4501 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4503 #define PUSH1(att) attribs[nAttribs++] = (att);
4504 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4506 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4507 PUSH2(GLX_X_RENDERABLE, TRUE);
4508 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4510 switch (BackBufferFormat) {
4511 /* color buffer */
4512 case D3DFMT_P8:
4513 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4514 PUSH2(GLX_BUFFER_SIZE, 8);
4515 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4516 break;
4518 case D3DFMT_R3G3B2:
4519 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4520 PUSH2(GLX_RED_SIZE, 3);
4521 PUSH2(GLX_GREEN_SIZE, 3);
4522 PUSH2(GLX_BLUE_SIZE, 2);
4523 break;
4525 case D3DFMT_A1R5G5B5:
4526 PUSH2(GLX_ALPHA_SIZE, 1);
4527 case D3DFMT_X1R5G5B5:
4528 PUSH2(GLX_RED_SIZE, 5);
4529 PUSH2(GLX_GREEN_SIZE, 5);
4530 PUSH2(GLX_BLUE_SIZE, 5);
4531 break;
4533 case D3DFMT_R5G6B5:
4534 PUSH2(GLX_RED_SIZE, 5);
4535 PUSH2(GLX_GREEN_SIZE, 6);
4536 PUSH2(GLX_BLUE_SIZE, 5);
4537 break;
4539 case D3DFMT_A4R4G4B4:
4540 PUSH2(GLX_ALPHA_SIZE, 4);
4541 case D3DFMT_X4R4G4B4:
4542 PUSH2(GLX_RED_SIZE, 4);
4543 PUSH2(GLX_GREEN_SIZE, 4);
4544 PUSH2(GLX_BLUE_SIZE, 4);
4545 break;
4547 case D3DFMT_A8R8G8B8:
4548 PUSH2(GLX_ALPHA_SIZE, 8);
4549 case D3DFMT_R8G8B8:
4550 case D3DFMT_X8R8G8B8:
4551 PUSH2(GLX_RED_SIZE, 8);
4552 PUSH2(GLX_GREEN_SIZE, 8);
4553 PUSH2(GLX_BLUE_SIZE, 8);
4554 break;
4556 default:
4557 break;
4560 switch (StencilBufferFormat) {
4561 case D3DFMT_D16_LOCKABLE:
4562 case D3DFMT_D16:
4563 PUSH2(GLX_DEPTH_SIZE, 16);
4564 break;
4566 case D3DFMT_D15S1:
4567 PUSH2(GLX_DEPTH_SIZE, 15);
4568 break;
4570 case D3DFMT_D24X8:
4571 PUSH2(GLX_DEPTH_SIZE, 24);
4572 break;
4574 case D3DFMT_D24X4S4:
4575 PUSH2(GLX_DEPTH_SIZE, 24);
4576 PUSH2(GLX_STENCIL_SIZE, 4);
4577 break;
4579 case D3DFMT_D24S8:
4580 PUSH2(GLX_DEPTH_SIZE, 24);
4581 PUSH2(GLX_STENCIL_SIZE, 8);
4582 break;
4584 case D3DFMT_D32:
4585 PUSH2(GLX_DEPTH_SIZE, 32);
4586 break;
4588 default:
4589 break;
4592 PUSH1(None);
4594 ENTER_GL();
4596 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4597 if (NULL != cfgs) {
4598 #ifdef EXTRA_TRACES
4599 int i;
4600 for (i = 0; i < nCfgs; ++i) {
4601 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4603 #endif
4605 if (NULL != This->renderTarget) {
4606 /*GLenum prev_read; */
4607 glFlush();
4608 vcheckGLcall("glFlush");
4610 #ifdef EXTRA_TRACES
4611 /** very very useful debug code */
4612 glXSwapBuffers(This->display, This->drawable);
4613 printf("Hit Enter to get next frame ...\n");
4614 getchar();
4615 #endif
4617 #if 0
4618 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4619 vcheckGLcall("glIntegerv");
4620 glReadBuffer(GL_BACK);
4621 vcheckGLcall("glReadBuffer");
4623 long j;
4624 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4626 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4627 pitch = pitch / 2;
4629 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4630 glReadPixels(0,
4631 This->renderTarget->myDesc.Height - j - 1,
4632 This->renderTarget->myDesc.Width,
4634 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4635 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4636 This->renderTarget->allocatedMemory + j * pitch);
4637 vcheckGLcall("glReadPixels");
4640 glReadBuffer(prev_read);
4641 vcheckGLcall("glReadBuffer");
4642 #endif
4645 if (BackBufferFormat != This->renderTarget->myDesc.Format &&
4646 StencilBufferFormat != This->stencilBufferTarget->myDesc.Format) {
4647 nAttribs = 0;
4648 PUSH2(GLX_PBUFFER_WIDTH, Width);
4649 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4650 PUSH1(None);
4651 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4653 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4654 if (NULL == This->render_ctx) {
4655 ERR("cannot create glxContext\n");
4658 glFlush();
4659 glXSwapBuffers(This->display, This->drawable);
4660 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4661 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4663 checkGLcall("glXMakeContextCurrent");
4666 tmp = This->renderTarget;
4667 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4668 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4669 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4671 tmp = This->stencilBufferTarget;
4672 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4673 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4674 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4677 DWORD value;
4678 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4679 This->renderUpsideDown = (This->renderTarget != This->frontBuffer) && (This->renderTarget != This->backBuffer);
4680 /* Force updating the cull mode */
4681 IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4682 IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4683 /* Force updating projection matrix */
4684 This->last_was_rhw = FALSE;
4685 This->proj_valid = FALSE;
4688 ret = D3D_OK;
4690 } else {
4691 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4694 #undef PUSH1
4695 #undef PUSH2
4697 LEAVE_GL();
4699 #endif
4701 return ret;