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
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
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 */
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];
55 #ifdef FRAME_DEBUGGING
57 BOOL isDumpingFrames = FALSE;
62 * Utility functions or macros
64 #define conv_mat(mat,gl_mat) \
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)); \
73 /* Apply the current values to the specified texture stage */
74 void setupTextureStates(LPDIRECT3DDEVICE8 iface, DWORD Stage, DWORD Flags) {
75 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
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++) {
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 */
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
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 */
107 case D3DTSS_TEXCOORDINDEX:
108 if (!(Flags == REAPPLY_ALL)) skip=TRUE;
112 if (!(Flags & REAPPLY_ALPHAOP)) skip=TRUE;
120 /* Performance: Only change to this texture if we have to */
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");
128 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
129 checkGLcall("glActiveTextureARB");
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 static void setup_light(LPDIRECT3DDEVICE8 iface, LONG Index, PLIGHTINFOEL *lightInfo) {
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);
162 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
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");
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");
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) {
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");
211 glLightfv(GL_LIGHT0+Index, GL_POSITION, &lightInfo->lightPosn[0]);
212 checkGLcall("glLightfv");
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");
223 case D3DLIGHT_DIRECTIONAL:
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");
234 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
237 /* Restore the modelview matrix */
241 /* Setup this textures matrix */
242 static void set_texture_matrix(const float *smat, DWORD flags)
246 glMatrixMode(GL_TEXTURE);
248 if (flags == D3DTTFF_DISABLE) {
250 checkGLcall("glLoadIdentity()");
254 if (flags == (D3DTTFF_COUNT1|D3DTTFF_PROJECTED)) {
255 ERR("Invalid texture transform flags: D3DTTFF_COUNT1|D3DTTFF_PROJECTED\n");
256 checkGLcall("glLoadIdentity()");
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) {
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;
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;
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);
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);
307 /* The function below is needed during the D3D8->WineD3D transition
308 in order to release various surfaces like the front- and backBuffer.
309 When the transition is complete code similar to this will be executed
310 by IWineD3DDevice_Release.
312 void IDirect3DDevice8_CleanUp(IDirect3DDevice8Impl *This)
314 LPDIRECT3DSURFACE8 stencilBufferParent;
315 /* Release the buffers (with sanity checks)*/
316 if(This->stencilBufferTarget != NULL && (IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8)This->stencilBufferTarget) >0)){
317 if(This->depthStencilBuffer != This->stencilBufferTarget)
318 TRACE("(%p) Something's still holding the depthStencilBuffer\n",This);
320 This->stencilBufferTarget = NULL;
322 if(This->renderTarget != NULL) {
323 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8)This->renderTarget);
324 This->renderTarget = NULL;
327 if(This->depthStencilBuffer != NULL) {
328 stencilBufferParent = (LPDIRECT3DSURFACE8)D3D8_SURFACE(This->depthStencilBuffer)->resource.parent;
329 if(stencilBufferParent != NULL) {
330 IDirect3DSurface8_Release(stencilBufferParent);
331 This->depthStencilBuffer = NULL;
335 if(This->backBuffer != NULL) {
336 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8)This->backBuffer);
337 This->backBuffer = NULL;
340 if(This->frontBuffer != NULL) {
341 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8)This->frontBuffer);
342 This->frontBuffer = NULL;
346 ULONG WINAPI IDirect3DDevice8Impl_Release(LPDIRECT3DDEVICE8 iface) {
347 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
348 ULONG ref = InterlockedDecrement(&This->ref);
350 TRACE("(%p) : ReleaseRef to %ld\n", This, ref);
353 IDirect3DDevice8Impl_CleanRender(iface);
354 IDirect3D8_Release((LPDIRECT3D8) This->direct3d8);
355 IDirect3DDevice8_CleanUp(This);
356 IWineD3DDevice_Release(This->WineD3DDevice);
357 if (glXGetCurrentContext() == This->glCtx) {
358 glXMakeCurrent(This->display, None, NULL);
360 glXDestroyContext(This->display, This->glCtx);
362 HeapFree(GetProcessHeap(), 0, This);
367 /* IDirect3DDevice Interface follow: */
368 HRESULT WINAPI IDirect3DDevice8Impl_TestCooperativeLevel(LPDIRECT3DDEVICE8 iface) {
369 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
370 TRACE("(%p) : stub\n", This); /* No way of notifying yet! */
374 UINT WINAPI IDirect3DDevice8Impl_GetAvailableTextureMem(LPDIRECT3DDEVICE8 iface) {
375 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
376 TRACE("(%p) : stub, emulating 32Mb for now\n", This);
378 * pretend we have 32MB of any type of memory queried.
380 return (1024*1024*32);
383 HRESULT WINAPI IDirect3DDevice8Impl_ResourceManagerDiscardBytes(LPDIRECT3DDEVICE8 iface, DWORD Bytes) {
384 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
385 FIXME("(%p) : stub\n", This);
388 HRESULT WINAPI IDirect3DDevice8Impl_GetDirect3D(LPDIRECT3DDEVICE8 iface, IDirect3D8** ppD3D8) {
389 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
390 TRACE("(%p) : returning %p\n", This, This->direct3d8);
393 IDirect3D8_AddRef((LPDIRECT3D8) This->direct3d8);
395 *ppD3D8 = (IDirect3D8 *)This->direct3d8;
398 HRESULT WINAPI IDirect3DDevice8Impl_GetDeviceCaps(LPDIRECT3DDEVICE8 iface, D3DCAPS8* pCaps) {
399 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
400 FIXME("(%p) : stub, calling idirect3d for now\n", This);
401 IDirect3D8Impl_GetDeviceCaps((LPDIRECT3D8) This->direct3d8, This->adapterNo, This->devType, pCaps);
404 HRESULT WINAPI IDirect3DDevice8Impl_GetDisplayMode(LPDIRECT3DDEVICE8 iface, D3DDISPLAYMODE* pMode) {
409 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
410 pMode->Width = GetSystemMetrics(SM_CXSCREEN);
411 pMode->Height = GetSystemMetrics(SM_CYSCREEN);
412 pMode->RefreshRate = 85; /*FIXME: How to identify? */
414 hdc = CreateDCA("DISPLAY", NULL, NULL, NULL);
415 bpp = GetDeviceCaps(hdc, BITSPIXEL);
419 case 8: pMode->Format = D3DFMT_R8G8B8; break;
420 case 16: pMode->Format = D3DFMT_R5G6B5; break;
421 case 24: /*pMode->Format = D3DFMT_R8G8B8; break; */
422 case 32: pMode->Format = D3DFMT_A8R8G8B8; break;
424 FIXME("Unrecognized display mode format\n");
425 pMode->Format = D3DFMT_UNKNOWN;
428 FIXME("(%p) : returning w(%d) h(%d) rr(%d) fmt(%u,%s)\n", This, pMode->Width, pMode->Height, pMode->RefreshRate,
429 pMode->Format, debug_d3dformat(pMode->Format));
432 HRESULT WINAPI IDirect3DDevice8Impl_GetCreationParameters(LPDIRECT3DDEVICE8 iface, D3DDEVICE_CREATION_PARAMETERS *pParameters) {
433 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
434 TRACE("(%p) copying to %p\n", This, pParameters);
435 memcpy(pParameters, &This->CreateParms, sizeof(D3DDEVICE_CREATION_PARAMETERS));
438 HRESULT WINAPI IDirect3DDevice8Impl_SetCursorProperties(LPDIRECT3DDEVICE8 iface, UINT XHotSpot, UINT YHotSpot, IDirect3DSurface8* pCursorBitmap) {
439 IDirect3DSurface8Impl* pSur = (IDirect3DSurface8Impl*) pCursorBitmap;
440 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
441 TRACE("(%p) : Spot Pos(%u,%u)\n", This, XHotSpot, YHotSpot);
443 if (D3DFMT_A8R8G8B8 != D3D8_SURFACE(pSur)->resource.format) {
444 ERR("(%p) : surface(%p) has an invalid format\n", This, pCursorBitmap);
445 return D3DERR_INVALIDCALL;
447 if (32 != D3D8_SURFACE(pSur)->currentDesc.Height || 32 != D3D8_SURFACE(pSur)->currentDesc.Width) {
448 ERR("(%p) : surface(%p) has an invalid size\n", This, pCursorBitmap);
449 return D3DERR_INVALIDCALL;
452 This->xHotSpot = XHotSpot;
453 This->yHotSpot = YHotSpot;
456 void WINAPI IDirect3DDevice8Impl_SetCursorPosition(LPDIRECT3DDEVICE8 iface, UINT XScreenSpace, UINT YScreenSpace, DWORD Flags) {
457 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
458 TRACE("(%p) : SetPos to (%u,%u)\n", This, XScreenSpace, YScreenSpace);
459 This->xScreenSpace = XScreenSpace;
460 This->yScreenSpace = YScreenSpace;
463 BOOL WINAPI IDirect3DDevice8Impl_ShowCursor(LPDIRECT3DDEVICE8 iface, BOOL bShow) {
464 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
465 TRACE("(%p) : visible(%d)\n", This, bShow);
466 This->bCursorVisible = bShow;
469 HRESULT WINAPI IDirect3DDevice8Impl_CreateAdditionalSwapChain(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters, IDirect3DSwapChain8** pSwapChain) {
470 IDirect3DSwapChain8Impl* object;
471 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
472 FIXME("(%p) : stub\n", This);
474 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDevice8Impl));
475 if (NULL == object) {
476 return D3DERR_OUTOFVIDEOMEMORY;
478 object->lpVtbl = &Direct3DSwapChain8_Vtbl;
481 TRACE("(%p)->(DepthStencil:(%u,%s), BackBufferFormat:(%u,%s))\n", This,
482 pPresentationParameters->AutoDepthStencilFormat, debug_d3dformat(pPresentationParameters->AutoDepthStencilFormat),
483 pPresentationParameters->BackBufferFormat, debug_d3dformat(pPresentationParameters->BackBufferFormat));
485 if (pPresentationParameters->Windowed && ((pPresentationParameters->BackBufferWidth == 0) ||
486 (pPresentationParameters->BackBufferHeight == 0))) {
489 GetClientRect(This->win_handle, &Rect);
491 if (pPresentationParameters->BackBufferWidth == 0) {
492 pPresentationParameters->BackBufferWidth = Rect.right;
493 TRACE("Updating width to %d\n", pPresentationParameters->BackBufferWidth);
495 if (pPresentationParameters->BackBufferHeight == 0) {
496 pPresentationParameters->BackBufferHeight = Rect.bottom;
497 TRACE("Updating height to %d\n", pPresentationParameters->BackBufferHeight);
501 /* Save the presentation parms now filled in correctly */
502 memcpy(&object->PresentParms, pPresentationParameters, sizeof(D3DPRESENT_PARAMETERS));
504 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
505 pPresentationParameters->BackBufferWidth,
506 pPresentationParameters->BackBufferHeight,
507 pPresentationParameters->BackBufferFormat,
508 pPresentationParameters->MultiSampleType,
510 (LPDIRECT3DSURFACE8*) &object->frontBuffer);
512 IDirect3DDevice8Impl_CreateRenderTarget((LPDIRECT3DDEVICE8) object,
513 pPresentationParameters->BackBufferWidth,
514 pPresentationParameters->BackBufferHeight,
515 pPresentationParameters->BackBufferFormat,
516 pPresentationParameters->MultiSampleType,
518 (LPDIRECT3DSURFACE8*) &object->backBuffer);
520 if (pPresentationParameters->EnableAutoDepthStencil) {
521 IDirect3DDevice8Impl_CreateDepthStencilSurface((LPDIRECT3DDEVICE8) object,
522 pPresentationParameters->BackBufferWidth,
523 pPresentationParameters->BackBufferHeight,
524 pPresentationParameters->AutoDepthStencilFormat,
526 (LPDIRECT3DSURFACE8*) &object->depthStencilBuffer);
528 object->depthStencilBuffer = NULL;
531 *pSwapChain = (IDirect3DSwapChain8*) object;
534 HRESULT WINAPI IDirect3DDevice8Impl_Reset(LPDIRECT3DDEVICE8 iface, D3DPRESENT_PARAMETERS* pPresentationParameters) {
535 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
536 FIXME("(%p) : stub\n", This);
539 HRESULT WINAPI IDirect3DDevice8Impl_Present(LPDIRECT3DDEVICE8 iface,
540 CONST RECT* pSourceRect, CONST RECT* pDestRect,
541 HWND hDestWindowOverride, CONST RGNDATA* pDirtyRegion) {
542 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
543 TRACE("(%p) : complete stub!\n", This);
547 if (pSourceRect || pDestRect) FIXME("Unhandled present options %p/%p\n", pSourceRect, pDestRect);
550 glXSwapBuffers(This->display, This->drawable);
551 /* Don't call checkGLcall, as glGetError is not applicable here */
552 TRACE("glXSwapBuffers called, Starting new frame\n");
555 if (TRACE_ON(d3d_fps))
557 static long prev_time, frames;
559 DWORD time = GetTickCount();
561 /* every 1.5 seconds */
562 if (time - prev_time > 1500) {
563 TRACE_(d3d_fps)("@ approx %.2ffps\n", 1000.0*frames/(time - prev_time));
569 #if defined(FRAME_DEBUGGING)
571 if (GetFileAttributesA("C:\\D3DTRACE") != INVALID_FILE_ATTRIBUTES) {
574 FIXME("Enabling D3D Trace\n");
575 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 1);
576 #if defined(SHOW_FRAME_MAKEUP)
577 FIXME("Singe Frame snapshots Starting\n");
578 isDumpingFrames = TRUE;
579 glClear(GL_COLOR_BUFFER_BIT);
582 #if defined(SINGLE_FRAME_DEBUGGING)
584 #if defined(SHOW_FRAME_MAKEUP)
585 FIXME("Singe Frame snapshots Finishing\n");
586 isDumpingFrames = FALSE;
588 FIXME("Singe Frame trace complete\n");
589 DeleteFileA("C:\\D3DTRACE");
590 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
596 #if defined(SHOW_FRAME_MAKEUP)
597 FIXME("Singe Frame snapshots Finishing\n");
598 isDumpingFrames = FALSE;
600 FIXME("Disabling D3D Trace\n");
601 __WINE_SET_DEBUGGING(__WINE_DBCL_TRACE, __wine_dbch_d3d, 0);
608 /* Although this is not strictly required, a simple demo showed this does occur
609 on (at least non-debug) d3d */
610 if (This->PresentParms.SwapEffect == D3DSWAPEFFECT_DISCARD) {
611 IDirect3DDevice8Impl_Clear(iface, 0, NULL, D3DCLEAR_STENCIL|D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 0x00, 1.0, 0);
616 HRESULT WINAPI IDirect3DDevice8Impl_GetBackBuffer(LPDIRECT3DDEVICE8 iface, UINT BackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface8** ppBackBuffer) {
617 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
618 *ppBackBuffer = (LPDIRECT3DSURFACE8) This->backBuffer;
619 TRACE("(%p) : BackBuf %d Type %d returning %p\n", This, BackBuffer, Type, *ppBackBuffer);
621 if (BackBuffer > This->PresentParms.BackBufferCount - 1) {
622 FIXME("Only one backBuffer currently supported\n");
623 return D3DERR_INVALIDCALL;
626 /* Note inc ref on returned surface */
627 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppBackBuffer);
631 HRESULT WINAPI IDirect3DDevice8Impl_GetRasterStatus(LPDIRECT3DDEVICE8 iface, D3DRASTER_STATUS* pRasterStatus) {
632 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
633 FIXME("(%p) : stub\n", This);
636 void WINAPI IDirect3DDevice8Impl_SetGammaRamp(LPDIRECT3DDEVICE8 iface, DWORD Flags, CONST D3DGAMMARAMP* pRamp) {
638 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
640 FIXME("(%p) : pRamp@%p\n", This, pRamp);
641 hDC = GetDC(This->win_handle);
642 SetDeviceGammaRamp(hDC, (LPVOID) pRamp);
643 ReleaseDC(This->win_handle, hDC);
646 void WINAPI IDirect3DDevice8Impl_GetGammaRamp(LPDIRECT3DDEVICE8 iface, D3DGAMMARAMP* pRamp) {
648 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
650 FIXME("(%p) : pRamp@%p\n", This, pRamp);
651 hDC = GetDC(This->win_handle);
652 GetDeviceGammaRamp(hDC, pRamp);
653 ReleaseDC(This->win_handle, hDC);
656 HRESULT WINAPI IDirect3DDevice8Impl_CreateTexture(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, UINT Levels, DWORD Usage,
657 D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture8 **ppTexture) {
658 IDirect3DTexture8Impl *object;
659 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
660 HRESULT hrc = D3D_OK;
662 TRACE("(%p) : W(%d) H(%d), Lvl(%d) d(%ld), Fmt(%u), Pool(%d)\n", This, Width, Height, Levels, Usage, Format, Pool);
664 /* Allocate the storage for the device */
665 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DTexture8Impl));
667 if (NULL == object) {
668 FIXME("Allocation of memory failed\n");
669 /* *ppTexture = NULL; */
670 return D3DERR_OUTOFVIDEOMEMORY;
673 object->lpVtbl = &Direct3DTexture8_Vtbl;
675 hrc = IWineD3DDevice_CreateTexture(This->WineD3DDevice, Width, Height, Levels, Usage,
676 (WINED3DFORMAT)Format, Pool, &object->wineD3DTexture, NULL, (IUnknown *)object, D3D8CB_CreateSurface);
680 FIXME("(%p) call to IWineD3DDevice_CreateTexture failed\n", This);
681 HeapFree(GetProcessHeap(), 0, object);
682 /* *ppTexture = NULL; */
684 *ppTexture = (LPDIRECT3DTEXTURE8) object;
687 TRACE("(%p) Created Texture %p, %p\n",This,object,object->wineD3DTexture);
690 HRESULT WINAPI IDirect3DDevice8Impl_CreateVolumeTexture(LPDIRECT3DDEVICE8 iface,
691 UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage,
692 D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture8** ppVolumeTexture) {
694 IDirect3DVolumeTexture8Impl *object;
695 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
696 HRESULT hrc = D3D_OK;
698 TRACE("(%p) Relay\n", This);
700 /* Allocate the storage for the device */
701 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVolumeTexture8Impl));
702 if (NULL == object) {
703 FIXME("(%p) allocation of memory failed\n", This);
704 *ppVolumeTexture = NULL;
705 return D3DERR_OUTOFVIDEOMEMORY;
708 object->lpVtbl = &Direct3DVolumeTexture8_Vtbl;
710 hrc = IWineD3DDevice_CreateVolumeTexture(This->WineD3DDevice, Width, Height, Depth, Levels, Usage,
711 (WINED3DFORMAT)Format, Pool, &object->wineD3DVolumeTexture, NULL,
712 (IUnknown *)object, D3D8CB_CreateVolume);
717 FIXME("(%p) call to IWineD3DDevice_CreateVolumeTexture failed\n", This);
718 HeapFree(GetProcessHeap(), 0, object);
719 *ppVolumeTexture = NULL;
721 *ppVolumeTexture = (LPDIRECT3DVOLUMETEXTURE8) object;
723 TRACE("(%p) returning %p\n", This , *ppVolumeTexture);
726 HRESULT WINAPI IDirect3DDevice8Impl_CreateCubeTexture(LPDIRECT3DDEVICE8 iface, UINT EdgeLength, UINT Levels, DWORD Usage,
727 D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture8** ppCubeTexture) {
729 IDirect3DCubeTexture8Impl *object;
730 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
733 TRACE("(%p) : ELen(%d) Lvl(%d) Usage(%ld) fmt(%u), Pool(%d)\n" , This, EdgeLength, Levels, Usage, Format, Pool);
735 /* Allocate the storage for the device */
736 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*object));
738 if (NULL == object) {
739 FIXME("(%p) allocation of CubeTexture failed\n", This);
740 *ppCubeTexture = NULL;
741 return D3DERR_OUTOFVIDEOMEMORY;
744 object->lpVtbl = &Direct3DCubeTexture8_Vtbl;
746 hr = IWineD3DDevice_CreateCubeTexture(This->WineD3DDevice, EdgeLength, Levels, Usage,
747 (WINED3DFORMAT)Format, Pool, &object->wineD3DCubeTexture, NULL, (IUnknown*)object,
748 D3D8CB_CreateSurface);
753 FIXME("(%p) call to IWineD3DDevice_CreateCubeTexture failed\n", This);
754 HeapFree(GetProcessHeap(), 0, object);
755 *ppCubeTexture = NULL;
757 *ppCubeTexture = (LPDIRECT3DCUBETEXTURE8) object;
760 TRACE("(%p) returning %p\n",This, *ppCubeTexture);
763 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexBuffer(LPDIRECT3DDEVICE8 iface, UINT Size, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer8** ppVertexBuffer) {
764 IDirect3DVertexBuffer8Impl *object;
766 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
768 /* Allocate the storage for the device */
769 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DVertexBuffer8Impl));
770 object->lpVtbl = &Direct3DVertexBuffer8_Vtbl;
771 object->Device = This;
772 object->ResourceType = D3DRTYPE_VERTEXBUFFER;
774 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Size);
775 object->currentDesc.Usage = Usage;
776 object->currentDesc.Pool = Pool;
777 object->currentDesc.FVF = FVF;
778 object->currentDesc.Size = Size;
780 TRACE("(%p) : Size=%d, Usage=%ld, FVF=%lx, Pool=%d - Memory@%p, Iface@%p\n", This, Size, Usage, FVF, Pool, object->allocatedMemory, object);
782 *ppVertexBuffer = (LPDIRECT3DVERTEXBUFFER8) object;
786 HRESULT WINAPI IDirect3DDevice8Impl_CreateIndexBuffer(LPDIRECT3DDEVICE8 iface, UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer8** ppIndexBuffer) {
787 IDirect3DIndexBuffer8Impl *object;
789 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
790 TRACE("(%p) : Len=%d, Use=%lx, Format=(%u,%s), Pool=%d\n", This, Length, Usage, Format, debug_d3dformat(Format), Pool);
792 /* Allocate the storage for the device */
793 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DIndexBuffer8Impl));
794 object->lpVtbl = &Direct3DIndexBuffer8_Vtbl;
795 object->Device = This;
797 object->ResourceType = D3DRTYPE_INDEXBUFFER;
799 object->currentDesc.Type = D3DRTYPE_INDEXBUFFER;
800 object->currentDesc.Usage = Usage;
801 object->currentDesc.Pool = Pool;
802 object->currentDesc.Format = Format;
803 object->currentDesc.Size = Length;
805 object->allocatedMemory = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);
807 TRACE("(%p) : Iface@%p allocatedMem @ %p\n", This, object, object->allocatedMemory);
809 *ppIndexBuffer = (LPDIRECT3DINDEXBUFFER8) object;
814 HRESULT WINAPI IDirect3DDevice8Impl_CreateSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, BOOL Lockable, BOOL Discard, UINT Level, IDirect3DSurface8 **ppSurface,D3DRESOURCETYPE Type, UINT Usage,D3DPOOL Pool, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality) {
816 IDirect3DSurface8Impl *object;
817 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
818 TRACE("(%p) Relay\n", This);
819 if(MultisampleQuality < 0) {
820 FIXME("MultisampleQuality out of range %ld, substituting 0 \n", MultisampleQuality);
821 /*FIXME: Find out what windows does with a MultisampleQuality < 0 */
822 MultisampleQuality=0;
825 if(MultisampleQuality > 0){
826 FIXME("MultisampleQuality set to %ld, bstituting 0 \n" , MultisampleQuality);
829 [in] Quality level. The valid range is between zero and one less than the level returned by pQualityLevels used by IDirect3D8::CheckDeviceMultiSampleType. Passing a larger value returns the error D3DERR_INVALIDCALL. The MultisampleQuality values of paired render targets, depth stencil surfaces, and the MultiSample type must all match.
831 MultisampleQuality=0;
833 /*FIXME: Check MAX bounds of MultisampleQuality*/
835 /* Allocate the storage for the device */
836 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DSurface8Impl));
837 if (NULL == object) {
838 FIXME("Allocation of memory failed\n");
840 return D3DERR_OUTOFVIDEOMEMORY;
843 object->lpVtbl = &Direct3DSurface8_Vtbl;
846 TRACE("(%p) : w(%d) h(%d) fmt(%d) surf@%p\n", This, Width, Height, Format, *ppSurface);
848 hrc = IWineD3DDevice_CreateSurface(This->WineD3DDevice, Width, Height, Format, Lockable, Discard, Level, &object->wineD3DSurface, Type, Usage, Pool,MultiSample,MultisampleQuality, NULL,(IUnknown *)object);
849 if (hrc != D3D_OK || NULL == object->wineD3DSurface) {
851 FIXME("(%p) call to IWineD3DDevice_CreateSurface failed\n", This);
852 HeapFree(GetProcessHeap(), 0, object);
855 *ppSurface = (LPDIRECT3DSURFACE8) object;
860 HRESULT WINAPI IDirect3DDevice8Impl_CreateRenderTarget(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, BOOL Lockable, IDirect3DSurface8** ppSurface) {
863 return IDirect3DDevice8Impl_CreateSurface(iface, Width, Height, Format, Lockable, FALSE /* Discard */, 0 /* Level */ , ppSurface, D3DRTYPE_SURFACE, D3DUSAGE_RENDERTARGET, D3DPOOL_DEFAULT, MultiSample, 0);
865 HRESULT WINAPI IDirect3DDevice8Impl_CreateDepthStencilSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, IDirect3DSurface8** ppSurface) {
867 /* TODO: Verify that Discard is false */
868 return IDirect3DDevice8Impl_CreateSurface(iface, Width, Height, Format, TRUE /* Lockable */, FALSE, 0 /* Level */
869 ,ppSurface, D3DRTYPE_SURFACE, D3DUSAGE_DEPTHSTENCIL,
870 D3DPOOL_DEFAULT, MultiSample, 0);
873 HRESULT WINAPI IDirect3DDevice8Impl_CreateImageSurface(LPDIRECT3DDEVICE8 iface, UINT Width, UINT Height, D3DFORMAT Format, IDirect3DSurface8** ppSurface) {
876 return IDirect3DDevice8Impl_CreateSurface(iface, Width, Height, Format, TRUE /* Loackable */ , FALSE /*Discard*/ , 0 /* Level */ , ppSurface, D3DRTYPE_SURFACE, 0 /* Usage (undefined/none) */ , D3DPOOL_SCRATCH, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */);
879 HRESULT WINAPI IDirect3DDevice8Impl_CopyRects(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8 *pSourceSurface, CONST RECT *pSourceRects, UINT cRects, IDirect3DSurface8 *pDestinationSurface, CONST POINT *pDestPoints) {
880 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
882 TRACE("(%p) Relay\n" , This);
884 return IWineD3DDevice_CopyRects(This->WineD3DDevice, pSourceSurface == NULL ? NULL : ((IDirect3DSurface8Impl *)pSourceSurface)->wineD3DSurface,
885 pSourceRects, cRects, pDestinationSurface == NULL ? NULL : ((IDirect3DSurface8Impl *)pDestinationSurface)->wineD3DSurface, pDestPoints);
888 HRESULT WINAPI IDirect3DDevice8Impl_UpdateTexture(LPDIRECT3DDEVICE8 iface, IDirect3DBaseTexture8* pSourceTexture, IDirect3DBaseTexture8* pDestinationTexture) {
889 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
890 TRACE("(%p) Relay\n" , This);
892 return IWineD3DDevice_UpdateTexture(This->WineD3DDevice, ((IDirect3DBaseTexture8Impl *)pSourceTexture)->wineD3DBaseTexture, ((IDirect3DBaseTexture8Impl *)pDestinationTexture)->wineD3DBaseTexture);
894 HRESULT WINAPI IDirect3DDevice8Impl_GetFrontBuffer(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pDestSurface) {
896 D3DLOCKED_RECT lockedRect;
901 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
903 FIXME("(%p) : Should return whole screen, only returns GL context window in top left corner\n", This);
905 if (D3DFMT_A8R8G8B8 != D3D8_SURFACE(((IDirect3DSurface8Impl*)pDestSurface))->resource.format) {
906 ERR("(%p) : surface(%p) has an invalid format\n", This, pDestSurface);
907 return D3DERR_INVALIDCALL;
912 wantedRect.right = This->PresentParms.BackBufferWidth;
913 wantedRect.bottom = This->PresentParms.BackBufferHeight;
915 hr = IDirect3DSurface8Impl_LockRect(pDestSurface, &lockedRect, &wantedRect, 0);
917 ERR("(%p) : cannot lock surface\n", This);
918 return D3DERR_INVALIDCALL;
924 vcheckGLcall("glFlush");
925 glGetIntegerv(GL_READ_BUFFER, &prev_read);
926 vcheckGLcall("glIntegerv");
927 glGetIntegerv(GL_PACK_SWAP_BYTES, &prev_store);
928 vcheckGLcall("glIntegerv");
930 glReadBuffer(GL_FRONT);
931 vcheckGLcall("glReadBuffer");
932 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
933 vcheckGLcall("glPixelStorei");
937 for (j = 0; j < This->PresentParms.BackBufferHeight; ++j) {
938 glReadPixels(0, This->PresentParms.BackBufferHeight - j - 1, This->PresentParms.BackBufferWidth, 1,
939 GL_BGRA, GL_UNSIGNED_BYTE, ((char*) lockedRect.pBits) + (j * lockedRect.Pitch));
940 vcheckGLcall("glReadPixels");
943 glPixelStorei(GL_PACK_SWAP_BYTES, prev_store);
944 vcheckGLcall("glPixelStorei");
945 glReadBuffer(prev_read);
946 vcheckGLcall("glReadBuffer");
950 hr = IDirect3DSurface8Impl_UnlockRect(pDestSurface);
953 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8* pRenderTarget, IDirect3DSurface8* pNewZStencil) {
955 D3DVIEWPORT8 viewport;
957 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
959 /* If pRenderTarget == NULL, it seems to default to back buffer */
960 if (pRenderTarget == NULL) pRenderTarget = (IDirect3DSurface8*)This->backBuffer;
962 /* For ease of code later on, handle a null depth as leave alone
963 - Have not tested real d3d for this case but doing this avoids
964 numerous null pointer checks */
965 if (pNewZStencil == NULL) pNewZStencil = (IDirect3DSurface8*)This->stencilBufferTarget;
967 /* If we are trying to set what we already have, don't bother */
968 if ((IDirect3DSurface8Impl*) pRenderTarget == This->renderTarget && (IDirect3DSurface8Impl*) pNewZStencil == This->stencilBufferTarget) {
969 TRACE("Trying to do a NOP SetRenderTarget operation\n");
971 /* Otherwise, set the render target up */
972 TRACE("(%p) : newRender@%p newZStencil@%p (default is backbuffer=(%p))\n", This, pRenderTarget, pNewZStencil, This->backBuffer);
973 IDirect3DDevice8Impl_CleanRender(iface);
974 hr = IDirect3DDevice8Impl_ActiveRender(iface, pRenderTarget, pNewZStencil);
978 /* Finally, reset the viewport as the MSDN states. */
979 viewport.Height = D3D8_SURFACE(((IDirect3DSurface8Impl*)pRenderTarget))->currentDesc.Height;
980 viewport.Width = D3D8_SURFACE(((IDirect3DSurface8Impl*)pRenderTarget))->currentDesc.Width;
983 viewport.MaxZ = 1.0f;
984 viewport.MinZ = 0.0f;
985 IDirect3DDevice8Impl_SetViewport(iface, &viewport);
991 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderTarget(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppRenderTarget) {
992 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
994 TRACE("(%p)->returning (%p) default is backbuffer=(%p)\n", This, This->renderTarget, This->backBuffer);
996 *ppRenderTarget = (LPDIRECT3DSURFACE8) This->renderTarget;
997 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppRenderTarget);
1002 HRESULT WINAPI IDirect3DDevice8Impl_GetDepthStencilSurface(LPDIRECT3DDEVICE8 iface, IDirect3DSurface8** ppZStencilSurface) {
1003 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1005 TRACE("(%p)->(%p) default(%p)\n", This, This->stencilBufferTarget, This->depthStencilBuffer);
1007 /* Note inc ref on returned surface */
1008 *ppZStencilSurface = (LPDIRECT3DSURFACE8) This->stencilBufferTarget;
1009 if (NULL != *ppZStencilSurface) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) *ppZStencilSurface);
1014 HRESULT WINAPI IDirect3DDevice8Impl_BeginScene(LPDIRECT3DDEVICE8 iface) {
1015 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1016 return IWineD3DDevice_BeginScene(This->WineD3DDevice);
1019 HRESULT WINAPI IDirect3DDevice8Impl_EndScene(LPDIRECT3DDEVICE8 iface) {
1020 IDirect3DBaseTexture8* cont = NULL;
1022 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1023 TRACE("(%p)\n", This);
1028 checkGLcall("glFlush");
1030 #if 0 /* Useful for debugging sometimes! */
1031 printf("Hit Enter ...\n");
1034 if ((This->frontBuffer != This->renderTarget) && (This->backBuffer != This->renderTarget)) {
1037 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1038 vcheckGLcall("glIntegerv");
1039 glReadBuffer(GL_FRONT);
1040 vcheckGLcall("glReadBuffer");
1043 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
1045 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
1048 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
1050 This->renderTarget->myDesc.Height - j - 1,
1051 This->renderTarget->myDesc.Width,
1053 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
1054 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
1055 This->renderTarget->allocatedMemory + j * pitch);
1056 vcheckGLcall("glReadPixels");
1059 glReadBuffer(prev_read);
1060 vcheckGLcall("glReadBuffer");
1063 hr = IDirect3DSurface8_GetContainer((LPDIRECT3DSURFACE8) This->renderTarget, &IID_IDirect3DBaseTexture8, (void**) &cont);
1064 if (SUCCEEDED(hr) && NULL != cont) {
1065 /** always dirtify for now. we must find a better way to see that surface have been modified */
1066 D3D8_SURFACE(This->renderTarget)->inPBuffer = TRUE;
1067 D3D8_SURFACE(This->renderTarget)->inTexture = FALSE;
1068 IDirect3DBaseTexture8Impl_SetDirty(cont, TRUE);
1069 IDirect3DBaseTexture8_PreLoad(cont);
1070 D3D8_SURFACE(This->renderTarget)->inPBuffer = FALSE;
1071 IDirect3DBaseTexture8Impl_Release(cont);
1079 HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count, CONST D3DRECT* pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) {
1080 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1082 /* TODO: From MSDN This method fails if you specify the D3DCLEAR_ZBUFFER or D3DCLEAR_STENCIL flags when the
1083 render target does not have an attached depth buffer. Similarly, if you specify the D3DCLEAR_STENCIL flag
1084 when the depth-buffer format does not contain stencil buffer information, this method fails. */
1085 GLbitfield glMask = 0;
1086 GLboolean old_ztest;
1087 GLfloat old_z_clear_value;
1088 GLint old_stencil_clear_value;
1089 GLfloat old_color_clear_value[4];
1091 CONST D3DRECT* curRect;
1093 TRACE("(%p) Count (%ld), pRects (%p), Flags (%lx), Z (%f), Stencil (%ld)\n", This,
1094 Count, pRects, Flags, Z, Stencil);
1097 glEnable(GL_SCISSOR_TEST);
1098 checkGLcall("glEnable GL_SCISSOR_TEST");
1099 if (Count > 0 && pRects) {
1105 /* Only set the values up once, as they are not changing */
1106 if (Flags & D3DCLEAR_STENCIL) {
1107 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1108 glClearStencil(Stencil);
1109 checkGLcall("glClearStencil");
1110 glMask = glMask | GL_STENCIL_BUFFER_BIT;
1111 glStencilMask(0xFFFFFFFF);
1114 if (Flags & D3DCLEAR_ZBUFFER) {
1115 glGetBooleanv(GL_DEPTH_WRITEMASK, &old_ztest);
1116 glDepthMask(GL_TRUE);
1117 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1119 checkGLcall("glClearDepth");
1120 glMask = glMask | GL_DEPTH_BUFFER_BIT;
1123 if (Flags & D3DCLEAR_TARGET) {
1124 TRACE("Clearing screen with glClear to color %lx\n", Color);
1125 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1126 glClearColor(D3DCOLOR_R(Color),
1130 checkGLcall("glClearColor");
1132 /* Clear ALL colors! */
1133 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1134 glMask = glMask | GL_COLOR_BUFFER_BIT;
1137 /* Now process each rect in turn */
1138 for (i = 0; i < Count || i == 0; i++) {
1141 /* Note gl uses lower left, width/height */
1142 TRACE("(%p) %p Rect=(%ld,%ld)->(%ld,%ld) glRect=(%ld,%ld), len=%ld, hei=%ld\n", This, curRect,
1143 curRect->x1, curRect->y1, curRect->x2, curRect->y2,
1144 curRect->x1, (D3D8_SURFACE(This->renderTarget)->currentDesc.Height - curRect->y2),
1145 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1146 glScissor(curRect->x1, (D3D8_SURFACE(This->renderTarget)->currentDesc.Height - curRect->y2),
1147 curRect->x2 - curRect->x1, curRect->y2 - curRect->y1);
1148 checkGLcall("glScissor");
1150 glScissor(This->StateBlock->viewport.X,
1151 (D3D8_SURFACE(This->renderTarget)->currentDesc.Height - (This->StateBlock->viewport.Y + This->StateBlock->viewport.Height)),
1152 This->StateBlock->viewport.Width,
1153 This->StateBlock->viewport.Height);
1154 checkGLcall("glScissor");
1157 /* Clear the selected rectangle (or full screen) */
1159 checkGLcall("glClear");
1161 /* Step to the next rectangle */
1162 if (curRect) curRect = curRect + sizeof(D3DRECT);
1165 /* Restore the old values (why..?) */
1166 if (Flags & D3DCLEAR_STENCIL) {
1167 glClearStencil(old_stencil_clear_value);
1168 glStencilMask(This->StateBlock->renderstate[D3DRS_STENCILWRITEMASK]);
1170 if (Flags & D3DCLEAR_ZBUFFER) {
1171 glDepthMask(old_ztest);
1172 glClearDepth(old_z_clear_value);
1174 if (Flags & D3DCLEAR_TARGET) {
1175 glClearColor(old_color_clear_value[0],
1176 old_color_clear_value[1],
1177 old_color_clear_value[2],
1178 old_color_clear_value[3]);
1179 glColorMask(This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1180 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1181 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
1182 This->StateBlock->renderstate[D3DRS_COLORWRITEENABLE] & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1185 glDisable(GL_SCISSOR_TEST);
1186 checkGLcall("glDisable");
1191 HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts, CONST D3DMATRIX* lpmatrix) {
1192 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1195 /* Most of this routine, comments included copied from ddraw tree initially: */
1196 TRACE("(%p) : State=%d\n", This, d3dts);
1198 /* Handle recording of state blocks */
1199 if (This->isRecordingState) {
1200 TRACE("Recording... not performing anything\n");
1201 This->UpdateStateBlock->Changed.transform[d3dts] = TRUE;
1202 This->UpdateStateBlock->Set.transform[d3dts] = TRUE;
1203 memcpy(&This->UpdateStateBlock->transforms[d3dts], lpmatrix, sizeof(D3DMATRIX));
1208 * if the new matrix is the same as the current one,
1209 * we cut off any further processing. this seems to be a reasonable
1210 * optimization because as was noticed, some apps (warcraft3 for example)
1211 * tend towards setting the same matrix repeatedly for some dumb reason.
1213 * From here on we assume that the new matrix is different, wherever it matters
1216 if (!memcmp(&This->StateBlock->transforms[d3dts].u.m[0][0], lpmatrix, sizeof(D3DMATRIX))) {
1217 TRACE("The app is setting the same matrix over again\n");
1220 conv_mat(lpmatrix, &This->StateBlock->transforms[d3dts].u.m[0][0]);
1224 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
1225 where ViewMat = Camera space, WorldMat = world space.
1227 In OpenGL, camera and world space is combined into GL_MODELVIEW
1228 matrix. The Projection matrix stay projection matrix.
1231 /* Capture the times we can just ignore the change */
1232 if (d3dts == D3DTS_WORLDMATRIX(0)) {
1233 This->modelview_valid = FALSE;
1236 } else if (d3dts == D3DTS_PROJECTION) {
1237 This->proj_valid = FALSE;
1240 } else if (d3dts >= D3DTS_WORLDMATRIX(1) && d3dts <= D3DTS_WORLDMATRIX(255)) { /* Indexed Vertex Blending Matrices 256 -> 511 */
1241 /* Use arb_vertex_blend or NV_VERTEX_WEIGHTING? */
1242 FIXME("D3DTS_WORLDMATRIX(1..255) not handled\n");
1246 /* Chances are we really are going to have to change a matrix */
1249 if (d3dts >= D3DTS_TEXTURE0 && d3dts <= D3DTS_TEXTURE7) { /* handle texture matrices */
1250 if (d3dts < GL_LIMITS(textures)) {
1251 int tex = d3dts - D3DTS_TEXTURE0;
1252 #if defined(GL_VERSION_1_3)
1253 glActiveTexture(GL_TEXTURE0 + tex);
1254 checkGLcall("glActiveTexture");
1256 glActiveTextureARB(GL_TEXTURE0_ARB + tex);
1257 checkGLcall("glActiveTextureARB");
1259 set_texture_matrix((const float *)lpmatrix, This->UpdateStateBlock->texture_state[tex][D3DTSS_TEXTURETRANSFORMFLAGS]);
1262 } else if (d3dts == D3DTS_VIEW) { /* handle the VIEW matrice */
1264 PLIGHTINFOEL *lightChain = NULL;
1265 float identity[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
1266 This->modelview_valid = FALSE;
1267 This->view_ident = !memcmp(lpmatrix, identity, 16*sizeof(float));
1268 glMatrixMode(GL_MODELVIEW);
1269 checkGLcall("glMatrixMode(GL_MODELVIEW)");
1271 glLoadMatrixf((const float *)lpmatrix);
1272 checkGLcall("glLoadMatrixf(...)");
1274 /* If we are changing the View matrix, reset the light and clipping planes to the new view
1275 * NOTE: We have to reset the positions even if the light/plane is not currently
1276 * enabled, since the call to enable it will not reset the position.
1277 * NOTE2: Apparently texture transforms do NOT need reapplying
1281 lightChain = This->StateBlock->lights;
1282 while (lightChain && lightChain->glIndex != -1) {
1283 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_POSITION, lightChain->lightPosn);
1284 checkGLcall("glLightfv posn");
1285 glLightfv(GL_LIGHT0 + lightChain->glIndex, GL_SPOT_DIRECTION, lightChain->lightDirn);
1286 checkGLcall("glLightfv dirn");
1287 lightChain = lightChain->next;
1289 /* Reset Clipping Planes if clipping is enabled */
1290 for (k = 0; k < GL_LIMITS(clipplanes); k++) {
1291 glClipPlane(GL_CLIP_PLANE0 + k, This->StateBlock->clipplane[k]);
1292 checkGLcall("glClipPlane");
1296 } else { /* What was requested!?? */
1297 WARN("invalid matrix specified: %i\n", d3dts);
1301 /* Release lock, all done */
1306 HRESULT WINAPI IDirect3DDevice8Impl_GetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State,D3DMATRIX* pMatrix) {
1307 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1308 TRACE("(%p) : for State %d\n", This, State);
1309 memcpy(pMatrix, &This->StateBlock->transforms[State], sizeof(D3DMATRIX));
1313 HRESULT WINAPI IDirect3DDevice8Impl_MultiplyTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX* pMatrix) {
1314 D3DMATRIX *mat = NULL;
1317 /* Note: Using UpdateStateBlock means it would be recorded in a state block change,
1318 but works regardless of recording being on.
1319 If this is found to be wrong, change to StateBlock. */
1320 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1321 TRACE("(%p) : For state %u\n", This, State);
1323 if (State < HIGHEST_TRANSFORMSTATE)
1325 mat = &This->UpdateStateBlock->transforms[State];
1327 FIXME("Unhandled transform state!!\n");
1330 /* Copied from ddraw code: */
1331 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);
1332 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);
1333 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);
1334 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);
1336 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);
1337 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);
1338 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);
1339 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);
1341 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);
1342 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);
1343 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);
1344 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);
1346 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);
1347 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);
1348 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);
1349 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);
1351 /* Apply change via set transform - will reapply to eg. lights this way */
1352 IDirect3DDevice8Impl_SetTransform(iface, State, &temp);
1355 HRESULT WINAPI IDirect3DDevice8Impl_SetViewport(LPDIRECT3DDEVICE8 iface, CONST D3DVIEWPORT8* pViewport) {
1356 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1358 TRACE("(%p)\n", This);
1359 This->UpdateStateBlock->Changed.viewport = TRUE;
1360 This->UpdateStateBlock->Set.viewport = TRUE;
1361 memcpy(&This->UpdateStateBlock->viewport, pViewport, sizeof(D3DVIEWPORT8));
1363 /* Handle recording of state blocks */
1364 if (This->isRecordingState) {
1365 TRACE("Recording... not performing anything\n");
1371 TRACE("(%p) : x=%ld, y=%ld, wid=%ld, hei=%ld, minz=%f, maxz=%f\n", This,
1372 pViewport->X, pViewport->Y, pViewport->Width, pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
1374 glDepthRange(pViewport->MinZ, pViewport->MaxZ);
1375 checkGLcall("glDepthRange");
1376 /* Note: GL requires lower left, DirectX supplies upper left */
1377 glViewport(pViewport->X, (D3D8_SURFACE(This->renderTarget)->currentDesc.Height - (pViewport->Y + pViewport->Height)),
1378 pViewport->Width, pViewport->Height);
1379 checkGLcall("glViewport");
1386 HRESULT WINAPI IDirect3DDevice8Impl_GetViewport(LPDIRECT3DDEVICE8 iface, D3DVIEWPORT8* pViewport) {
1387 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1388 TRACE("(%p)\n", This);
1389 memcpy(pViewport, &This->StateBlock->viewport, sizeof(D3DVIEWPORT8));
1393 HRESULT WINAPI IDirect3DDevice8Impl_SetMaterial(LPDIRECT3DDEVICE8 iface, CONST D3DMATERIAL8* pMaterial) {
1394 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1396 This->UpdateStateBlock->Changed.material = TRUE;
1397 This->UpdateStateBlock->Set.material = TRUE;
1398 memcpy(&This->UpdateStateBlock->material, pMaterial, sizeof(D3DMATERIAL8));
1400 /* Handle recording of state blocks */
1401 if (This->isRecordingState) {
1402 TRACE("Recording... not performing anything\n");
1407 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1408 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1409 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1410 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1411 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1413 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &This->UpdateStateBlock->material.Ambient);
1414 checkGLcall("glMaterialfv");
1415 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &This->UpdateStateBlock->material.Diffuse);
1416 checkGLcall("glMaterialfv");
1418 /* Only change material color if specular is enabled, otherwise it is set to black */
1419 if (This->StateBlock->renderstate[D3DRS_SPECULARENABLE]) {
1420 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
1421 checkGLcall("glMaterialfv");
1423 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
1424 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1425 checkGLcall("glMaterialfv");
1427 glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &This->UpdateStateBlock->material.Emissive);
1428 checkGLcall("glMaterialfv");
1429 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, This->UpdateStateBlock->material.Power);
1430 checkGLcall("glMaterialf");
1435 HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMATERIAL8* pMaterial) {
1436 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1437 memcpy(pMaterial, &This->UpdateStateBlock->material, sizeof (D3DMATERIAL8));
1438 TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", This, pMaterial->Diffuse.r, pMaterial->Diffuse.g, pMaterial->Diffuse.b, pMaterial->Diffuse.a);
1439 TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", This, pMaterial->Ambient.r, pMaterial->Ambient.g, pMaterial->Ambient.b, pMaterial->Ambient.a);
1440 TRACE("(%p) : Specular (%f,%f,%f,%f)\n", This, pMaterial->Specular.r, pMaterial->Specular.g, pMaterial->Specular.b, pMaterial->Specular.a);
1441 TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", This, pMaterial->Emissive.r, pMaterial->Emissive.g, pMaterial->Emissive.b, pMaterial->Emissive.a);
1442 TRACE("(%p) : Power (%f)\n", This, pMaterial->Power);
1446 /* Note lights are real special cases. Although the device caps state only eg. 8 are supported,
1447 you can reference any indexes you want as long as that number max are enabled are any
1448 one point in time! Therefore since the indexes can be anything, we need a linked list of them.
1449 However, this causes stateblock problems. When capturing the state block, I duplicate the list,
1450 but when recording, just build a chain pretty much of commands to be replayed. */
1452 HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index, CONST D3DLIGHT8* pLight) {
1454 PLIGHTINFOEL *object, *temp;
1456 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1457 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1459 /* If recording state block, just add to end of lights chain */
1460 if (This->isRecordingState) {
1461 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1462 if (NULL == object) {
1463 return D3DERR_OUTOFVIDEOMEMORY;
1465 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1466 object->OriginalIndex = Index;
1467 object->glIndex = -1;
1468 object->changed = TRUE;
1470 /* Add to the END of the chain of lights changes to be replayed */
1471 if (This->UpdateStateBlock->lights == NULL) {
1472 This->UpdateStateBlock->lights = object;
1474 temp = This->UpdateStateBlock->lights;
1475 while (temp->next != NULL) temp=temp->next;
1476 temp->next = object;
1478 TRACE("Recording... not performing anything more\n");
1482 /* Ok, not recording any longer so do real work */
1483 object = This->StateBlock->lights;
1484 while (object != NULL && object->OriginalIndex != Index) object = object->next;
1486 /* If we didn't find it in the list of lights, time to add it */
1487 if (object == NULL) {
1488 PLIGHTINFOEL *insertAt,*prevPos;
1490 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1491 if (NULL == object) {
1492 return D3DERR_OUTOFVIDEOMEMORY;
1494 object->OriginalIndex = Index;
1495 object->glIndex = -1;
1497 /* Add it to the front of list with the idea that lights will be changed as needed
1498 BUT after any lights currently assigned GL indexes */
1499 insertAt = This->StateBlock->lights;
1501 while (insertAt != NULL && insertAt->glIndex != -1) {
1503 insertAt = insertAt->next;
1506 if (insertAt == NULL && prevPos == NULL) { /* Start of list */
1507 This->StateBlock->lights = object;
1508 } else if (insertAt == NULL) { /* End of list */
1509 prevPos->next = object;
1510 object->prev = prevPos;
1511 } else { /* Middle of chain */
1512 if (prevPos == NULL) {
1513 This->StateBlock->lights = object;
1515 prevPos->next = object;
1517 object->prev = prevPos;
1518 object->next = insertAt;
1519 insertAt->prev = object;
1523 /* Initialze the object */
1524 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,
1525 pLight->Diffuse.r, pLight->Diffuse.g, pLight->Diffuse.b, pLight->Diffuse.a,
1526 pLight->Specular.r, pLight->Specular.g, pLight->Specular.b, pLight->Specular.a,
1527 pLight->Ambient.r, pLight->Ambient.g, pLight->Ambient.b, pLight->Ambient.a);
1528 TRACE("... Pos(%f,%f,%f), Dirn(%f,%f,%f)\n", pLight->Position.x, pLight->Position.y, pLight->Position.z,
1529 pLight->Direction.x, pLight->Direction.y, pLight->Direction.z);
1530 TRACE("... Range(%f), Falloff(%f), Theta(%f), Phi(%f)\n", pLight->Range, pLight->Falloff, pLight->Theta, pLight->Phi);
1532 /* Save away the information */
1533 memcpy(&object->OriginalParms, pLight, sizeof(D3DLIGHT8));
1535 switch (pLight->Type) {
1536 case D3DLIGHT_POINT:
1538 object->lightPosn[0] = pLight->Position.x;
1539 object->lightPosn[1] = pLight->Position.y;
1540 object->lightPosn[2] = pLight->Position.z;
1541 object->lightPosn[3] = 1.0f;
1542 object->cutoff = 180.0f;
1546 case D3DLIGHT_DIRECTIONAL:
1548 object->lightPosn[0] = -pLight->Direction.x;
1549 object->lightPosn[1] = -pLight->Direction.y;
1550 object->lightPosn[2] = -pLight->Direction.z;
1551 object->lightPosn[3] = 0.0;
1552 object->exponent = 0.0f;
1553 object->cutoff = 180.0f;
1558 object->lightPosn[0] = pLight->Position.x;
1559 object->lightPosn[1] = pLight->Position.y;
1560 object->lightPosn[2] = pLight->Position.z;
1561 object->lightPosn[3] = 1.0;
1564 object->lightDirn[0] = pLight->Direction.x;
1565 object->lightDirn[1] = pLight->Direction.y;
1566 object->lightDirn[2] = pLight->Direction.z;
1567 object->lightDirn[3] = 1.0;
1570 * opengl-ish and d3d-ish spot lights use too different models for the
1571 * light "intensity" as a function of the angle towards the main light direction,
1572 * so we only can approximate very roughly.
1573 * however spot lights are rather rarely used in games (if ever used at all).
1574 * furthermore if still used, probably nobody pays attention to such details.
1576 if (pLight->Falloff == 0) {
1579 rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
1581 if (rho < 0.0001) rho = 0.0001f;
1582 object->exponent = -0.3/log(cos(rho/2));
1583 object->cutoff = pLight->Phi*90/M_PI;
1589 FIXME("Unrecognized light type %d\n", pLight->Type);
1592 /* Update the live definitions if the light is currently assigned a glIndex */
1593 if (object->glIndex != -1) {
1594 setup_light(iface, object->glIndex, object);
1598 HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
1599 PLIGHTINFOEL *lightInfo = NULL;
1600 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1601 TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
1603 /* Locate the light in the live lights */
1604 lightInfo = This->StateBlock->lights;
1605 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1607 if (lightInfo == NULL) {
1608 TRACE("Light information requested but light not defined\n");
1609 return D3DERR_INVALIDCALL;
1612 memcpy(pLight, &lightInfo->OriginalParms, sizeof(D3DLIGHT8));
1615 HRESULT WINAPI IDirect3DDevice8Impl_LightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL Enable) {
1616 PLIGHTINFOEL *lightInfo = NULL;
1617 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1618 TRACE("(%p) : Idx(%ld), enable? %d\n", This, Index, Enable);
1620 /* If recording state block, just add to end of lights chain with changedEnable set to true */
1621 if (This->isRecordingState) {
1622 lightInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PLIGHTINFOEL));
1623 if (NULL == lightInfo) {
1624 return D3DERR_OUTOFVIDEOMEMORY;
1626 lightInfo->OriginalIndex = Index;
1627 lightInfo->glIndex = -1;
1628 lightInfo->enabledChanged = TRUE;
1630 /* Add to the END of the chain of lights changes to be replayed */
1631 if (This->UpdateStateBlock->lights == NULL) {
1632 This->UpdateStateBlock->lights = lightInfo;
1634 PLIGHTINFOEL *temp = This->UpdateStateBlock->lights;
1635 while (temp->next != NULL) temp=temp->next;
1636 temp->next = lightInfo;
1638 TRACE("Recording... not performing anything more\n");
1642 /* Not recording... So, locate the light in the live lights */
1643 lightInfo = This->StateBlock->lights;
1644 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1646 /* Special case - enabling an undefined light creates one with a strict set of parms! */
1647 if (lightInfo == NULL) {
1648 D3DLIGHT8 lightParms;
1649 /* Warning - untested code :-) Prob safe to change fixme to a trace but
1650 wait until someone confirms it seems to work! */
1651 TRACE("Light enabled requested but light not defined, so defining one!\n");
1652 lightParms.Type = D3DLIGHT_DIRECTIONAL;
1653 lightParms.Diffuse.r = 1.0;
1654 lightParms.Diffuse.g = 1.0;
1655 lightParms.Diffuse.b = 1.0;
1656 lightParms.Diffuse.a = 0.0;
1657 lightParms.Specular.r = 0.0;
1658 lightParms.Specular.g = 0.0;
1659 lightParms.Specular.b = 0.0;
1660 lightParms.Specular.a = 0.0;
1661 lightParms.Ambient.r = 0.0;
1662 lightParms.Ambient.g = 0.0;
1663 lightParms.Ambient.b = 0.0;
1664 lightParms.Ambient.a = 0.0;
1665 lightParms.Position.x = 0.0;
1666 lightParms.Position.y = 0.0;
1667 lightParms.Position.z = 0.0;
1668 lightParms.Direction.x = 0.0;
1669 lightParms.Direction.y = 0.0;
1670 lightParms.Direction.z = 1.0;
1671 lightParms.Range = 0.0;
1672 lightParms.Falloff = 0.0;
1673 lightParms.Attenuation0 = 0.0;
1674 lightParms.Attenuation1 = 0.0;
1675 lightParms.Attenuation2 = 0.0;
1676 lightParms.Theta = 0.0;
1677 lightParms.Phi = 0.0;
1678 IDirect3DDevice8Impl_SetLight(iface, Index, &lightParms);
1680 /* Search for it again! Should be fairly quick as near head of list */
1681 lightInfo = This->StateBlock->lights;
1682 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1683 if (lightInfo == NULL) {
1684 FIXME("Adding default lights has failed dismally\n");
1685 return D3DERR_INVALIDCALL;
1689 /* OK, we now have a light... */
1690 if (Enable == FALSE) {
1692 /* If we are disabling it, check it was enabled, and
1693 still only do something if it has assigned a glIndex (which it should have!) */
1694 if (lightInfo->lightEnabled && (lightInfo->glIndex != -1)) {
1695 TRACE("Disabling light set up at gl idx %ld\n", lightInfo->glIndex);
1697 glDisable(GL_LIGHT0 + lightInfo->glIndex);
1698 checkGLcall("glDisable GL_LIGHT0+Index");
1701 TRACE("Nothing to do as light was not enabled\n");
1703 lightInfo->lightEnabled = FALSE;
1706 /* We are enabling it. If it is enabled, its really simple */
1707 if (lightInfo->lightEnabled) {
1709 TRACE("Nothing to do as light was enabled\n");
1711 /* If it already has a glIndex, its still simple */
1712 } else if (lightInfo->glIndex != -1) {
1713 TRACE("Reusing light as already set up at gl idx %ld\n", lightInfo->glIndex);
1714 lightInfo->lightEnabled = TRUE;
1716 glEnable(GL_LIGHT0 + lightInfo->glIndex);
1717 checkGLcall("glEnable GL_LIGHT0+Index already setup");
1720 /* Otherwise got to find space - lights are ordered gl indexes first */
1722 PLIGHTINFOEL *bsf = NULL;
1723 PLIGHTINFOEL *pos = This->StateBlock->lights;
1724 PLIGHTINFOEL *prev = NULL;
1728 /* Try to minimize changes as much as possible */
1729 while (pos != NULL && pos->glIndex != -1 && Index < This->maxConcurrentLights) {
1731 /* Try to remember which index can be replaced if necessary */
1732 if (bsf==NULL && pos->lightEnabled == FALSE) {
1733 /* Found a light we can replace, save as best replacement */
1737 /* Step to next space */
1743 /* If we have too many active lights, fail the call */
1744 if ((Index == This->maxConcurrentLights) && (bsf == NULL)) {
1745 FIXME("Program requests too many concurrent lights\n");
1746 return D3DERR_INVALIDCALL;
1748 /* If we have allocated all lights, but not all are enabled,
1749 reuse one which is not enabled */
1750 } else if (Index == This->maxConcurrentLights) {
1751 /* use bsf - Simply swap the new light and the BSF one */
1752 PLIGHTINFOEL *bsfNext = bsf->next;
1753 PLIGHTINFOEL *bsfPrev = bsf->prev;
1756 if (lightInfo->next != NULL) lightInfo->next->prev = bsf;
1757 if (bsf->prev != NULL) {
1758 bsf->prev->next = lightInfo;
1760 This->StateBlock->lights = lightInfo;
1763 /* If not side by side, lots of chains to update */
1764 if (bsf->next != lightInfo) {
1765 lightInfo->prev->next = bsf;
1766 bsf->next->prev = lightInfo;
1767 bsf->next = lightInfo->next;
1768 bsf->prev = lightInfo->prev;
1769 lightInfo->next = bsfNext;
1770 lightInfo->prev = bsfPrev;
1774 bsf->prev = lightInfo;
1775 bsf->next = lightInfo->next;
1776 lightInfo->next = bsf;
1777 lightInfo->prev = bsfPrev;
1782 glIndex = bsf->glIndex;
1784 lightInfo->glIndex = glIndex;
1785 lightInfo->lightEnabled = TRUE;
1787 /* Finally set up the light in gl itself */
1788 TRACE("Replacing light which was set up at gl idx %ld\n", lightInfo->glIndex);
1790 setup_light(iface, glIndex, lightInfo);
1791 glEnable(GL_LIGHT0 + glIndex);
1792 checkGLcall("glEnable GL_LIGHT0 new setup");
1795 /* If we reached the end of the allocated lights, with space in the
1796 gl lights, setup a new light */
1797 } else if (pos->glIndex == -1) {
1799 /* We reached the end of the allocated gl lights, so already
1800 know the index of the next one! */
1802 lightInfo->glIndex = glIndex;
1803 lightInfo->lightEnabled = TRUE;
1805 /* In an ideal world, its already in the right place */
1806 if (lightInfo->prev == NULL || lightInfo->prev->glIndex!=-1) {
1807 /* No need to move it */
1809 /* Remove this light from the list */
1810 lightInfo->prev->next = lightInfo->next;
1811 if (lightInfo->next != NULL) {
1812 lightInfo->next->prev = lightInfo->prev;
1815 /* Add in at appropriate place (inbetween prev and pos) */
1816 lightInfo->prev = prev;
1817 lightInfo->next = pos;
1819 This->StateBlock->lights = lightInfo;
1821 prev->next = lightInfo;
1824 pos->prev = lightInfo;
1828 /* Finally set up the light in gl itself */
1829 TRACE("Defining new light at gl idx %ld\n", lightInfo->glIndex);
1831 setup_light(iface, glIndex, lightInfo);
1832 glEnable(GL_LIGHT0 + glIndex);
1833 checkGLcall("glEnable GL_LIGHT0 new setup");
1841 HRESULT WINAPI IDirect3DDevice8Impl_GetLightEnable(LPDIRECT3DDEVICE8 iface, DWORD Index,BOOL* pEnable) {
1843 PLIGHTINFOEL *lightInfo = NULL;
1844 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1845 TRACE("(%p) : for idx(%ld)\n", This, Index);
1847 /* Locate the light in the live lights */
1848 lightInfo = This->StateBlock->lights;
1849 while (lightInfo != NULL && lightInfo->OriginalIndex != Index) lightInfo = lightInfo->next;
1851 if (lightInfo == NULL) {
1852 TRACE("Light enabled state requested but light not defined\n");
1853 return D3DERR_INVALIDCALL;
1855 *pEnable = lightInfo->lightEnabled;
1858 HRESULT WINAPI IDirect3DDevice8Impl_SetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST float* pPlane) {
1859 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1860 TRACE("(%p) : for idx %ld, %p\n", This, Index, pPlane);
1862 /* Validate Index */
1863 if (Index >= GL_LIMITS(clipplanes)) {
1864 TRACE("Application has requested clipplane this device doesn't support\n");
1865 return D3DERR_INVALIDCALL;
1868 This->UpdateStateBlock->Changed.clipplane[Index] = TRUE;
1869 This->UpdateStateBlock->Set.clipplane[Index] = TRUE;
1870 This->UpdateStateBlock->clipplane[Index][0] = pPlane[0];
1871 This->UpdateStateBlock->clipplane[Index][1] = pPlane[1];
1872 This->UpdateStateBlock->clipplane[Index][2] = pPlane[2];
1873 This->UpdateStateBlock->clipplane[Index][3] = pPlane[3];
1875 /* Handle recording of state blocks */
1876 if (This->isRecordingState) {
1877 TRACE("Recording... not performing anything\n");
1885 /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
1886 glMatrixMode(GL_MODELVIEW);
1888 glLoadMatrixf((float *) &This->StateBlock->transforms[D3DTS_VIEW].u.m[0][0]);
1890 TRACE("Clipplane [%f,%f,%f,%f]\n",
1891 This->UpdateStateBlock->clipplane[Index][0],
1892 This->UpdateStateBlock->clipplane[Index][1],
1893 This->UpdateStateBlock->clipplane[Index][2],
1894 This->UpdateStateBlock->clipplane[Index][3]);
1895 glClipPlane(GL_CLIP_PLANE0 + Index, This->UpdateStateBlock->clipplane[Index]);
1896 checkGLcall("glClipPlane");
1904 HRESULT WINAPI IDirect3DDevice8Impl_GetClipPlane(LPDIRECT3DDEVICE8 iface, DWORD Index,float* pPlane) {
1905 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1906 TRACE("(%p) : for idx %ld\n", This, Index);
1908 /* Validate Index */
1909 if (Index >= GL_LIMITS(clipplanes)) {
1910 TRACE("Application has requested clipplane this device doesn't support\n");
1911 return D3DERR_INVALIDCALL;
1914 pPlane[0] = This->StateBlock->clipplane[Index][0];
1915 pPlane[1] = This->StateBlock->clipplane[Index][1];
1916 pPlane[2] = This->StateBlock->clipplane[Index][2];
1917 pPlane[3] = This->StateBlock->clipplane[Index][3];
1920 HRESULT WINAPI IDirect3DDevice8Impl_SetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD Value) {
1925 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
1926 DWORD OldValue = This->StateBlock->renderstate[State];
1928 TRACE("(%p)->state = %s(%d), value = %ld\n", This, debug_d3drenderstate(State), State, Value);
1929 This->UpdateStateBlock->Changed.renderstate[State] = TRUE;
1930 This->UpdateStateBlock->Set.renderstate[State] = TRUE;
1931 This->UpdateStateBlock->renderstate[State] = Value;
1933 /* Handle recording of state blocks */
1934 if (This->isRecordingState) {
1935 TRACE("Recording... not performing anything\n");
1942 case D3DRS_FILLMODE :
1943 switch ((D3DFILLMODE) Value) {
1944 case D3DFILL_POINT : glPolygonMode(GL_FRONT_AND_BACK, GL_POINT); break;
1945 case D3DFILL_WIREFRAME : glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); break;
1946 case D3DFILL_SOLID : glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); break;
1948 FIXME("Unrecognized D3DRS_FILLMODE value %ld\n", Value);
1950 checkGLcall("glPolygonMode (fillmode)");
1953 case D3DRS_LIGHTING :
1955 glEnable(GL_LIGHTING);
1956 checkGLcall("glEnable GL_LIGHTING");
1958 glDisable(GL_LIGHTING);
1959 checkGLcall("glDisable GL_LIGHTING");
1963 case D3DRS_ZENABLE :
1964 switch ((D3DZBUFFERTYPE) Value) {
1966 glDisable(GL_DEPTH_TEST);
1967 checkGLcall("glDisable GL_DEPTH_TEST");
1970 glEnable(GL_DEPTH_TEST);
1971 checkGLcall("glEnable GL_DEPTH_TEST");
1974 glEnable(GL_DEPTH_TEST);
1975 checkGLcall("glEnable GL_DEPTH_TEST");
1976 FIXME("W buffer is not well handled\n");
1979 FIXME("Unrecognized D3DZBUFFERTYPE value %ld\n", Value);
1983 case D3DRS_CULLMODE :
1985 /* If we are culling "back faces with clockwise vertices" then
1986 set front faces to be counter clockwise and enable culling
1988 switch ((D3DCULL) Value) {
1990 glDisable(GL_CULL_FACE);
1991 checkGLcall("glDisable GL_CULL_FACE");
1994 glEnable(GL_CULL_FACE);
1995 checkGLcall("glEnable GL_CULL_FACE");
1996 if (This->renderUpsideDown) {
1998 checkGLcall("glFrontFace GL_CW");
2000 glFrontFace(GL_CCW);
2001 checkGLcall("glFrontFace GL_CCW");
2003 glCullFace(GL_BACK);
2006 glEnable(GL_CULL_FACE);
2007 checkGLcall("glEnable GL_CULL_FACE");
2008 if (This->renderUpsideDown) {
2009 glFrontFace(GL_CCW);
2010 checkGLcall("glFrontFace GL_CCW");
2013 checkGLcall("glFrontFace GL_CW");
2015 glCullFace(GL_BACK);
2018 FIXME("Unrecognized/Unhandled D3DCULL value %ld\n", Value);
2022 case D3DRS_SHADEMODE :
2023 switch ((D3DSHADEMODE) Value) {
2025 glShadeModel(GL_FLAT);
2026 checkGLcall("glShadeModel");
2028 case D3DSHADE_GOURAUD:
2029 glShadeModel(GL_SMOOTH);
2030 checkGLcall("glShadeModel");
2032 case D3DSHADE_PHONG:
2033 FIXME("D3DSHADE_PHONG isn't supported?\n");
2036 return D3DERR_INVALIDCALL;
2038 FIXME("Unrecognized/Unhandled D3DSHADEMODE value %ld\n", Value);
2042 case D3DRS_DITHERENABLE :
2044 glEnable(GL_DITHER);
2045 checkGLcall("glEnable GL_DITHER");
2047 glDisable(GL_DITHER);
2048 checkGLcall("glDisable GL_DITHER");
2052 case D3DRS_ZWRITEENABLE :
2055 checkGLcall("glDepthMask");
2058 checkGLcall("glDepthMask");
2064 int glParm = GL_LESS;
2066 switch ((D3DCMPFUNC) Value) {
2067 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2068 case D3DCMP_LESS: glParm=GL_LESS; break;
2069 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2070 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2071 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2072 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2073 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2074 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2076 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2078 glDepthFunc(glParm);
2079 checkGLcall("glDepthFunc");
2083 case D3DRS_AMBIENT :
2086 D3DCOLORTOGLFLOAT4(Value, col);
2087 TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
2088 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
2089 checkGLcall("glLightModel for MODEL_AMBIENT");
2094 case D3DRS_ALPHABLENDENABLE :
2097 checkGLcall("glEnable GL_BLEND");
2099 glDisable(GL_BLEND);
2100 checkGLcall("glDisable GL_BLEND");
2104 case D3DRS_SRCBLEND :
2105 case D3DRS_DESTBLEND :
2107 int newVal = GL_ZERO;
2109 case D3DBLEND_ZERO : newVal = GL_ZERO; break;
2110 case D3DBLEND_ONE : newVal = GL_ONE; break;
2111 case D3DBLEND_SRCCOLOR : newVal = GL_SRC_COLOR; break;
2112 case D3DBLEND_INVSRCCOLOR : newVal = GL_ONE_MINUS_SRC_COLOR; break;
2113 case D3DBLEND_SRCALPHA : newVal = GL_SRC_ALPHA; break;
2114 case D3DBLEND_INVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA; break;
2115 case D3DBLEND_DESTALPHA : newVal = GL_DST_ALPHA; break;
2116 case D3DBLEND_INVDESTALPHA : newVal = GL_ONE_MINUS_DST_ALPHA; break;
2117 case D3DBLEND_DESTCOLOR : newVal = GL_DST_COLOR; break;
2118 case D3DBLEND_INVDESTCOLOR : newVal = GL_ONE_MINUS_DST_COLOR; break;
2119 case D3DBLEND_SRCALPHASAT : newVal = GL_SRC_ALPHA_SATURATE; break;
2121 case D3DBLEND_BOTHSRCALPHA : newVal = GL_SRC_ALPHA;
2122 This->srcBlend = newVal;
2123 This->dstBlend = newVal;
2126 case D3DBLEND_BOTHINVSRCALPHA : newVal = GL_ONE_MINUS_SRC_ALPHA;
2127 This->srcBlend = newVal;
2128 This->dstBlend = newVal;
2131 FIXME("Unrecognized src/dest blend value %ld (%d)\n", Value, State);
2134 if (State == D3DRS_SRCBLEND) This->srcBlend = newVal;
2135 if (State == D3DRS_DESTBLEND) This->dstBlend = newVal;
2136 TRACE("glBlendFunc src=%x, dst=%x\n", This->srcBlend, This->dstBlend);
2137 glBlendFunc(This->srcBlend, This->dstBlend);
2139 checkGLcall("glBlendFunc");
2143 case D3DRS_ALPHATESTENABLE :
2145 glEnable(GL_ALPHA_TEST);
2146 checkGLcall("glEnable GL_ALPHA_TEST");
2148 glDisable(GL_ALPHA_TEST);
2149 checkGLcall("glDisable GL_ALPHA_TEST");
2153 case D3DRS_ALPHAFUNC :
2155 int glParm = GL_LESS;
2156 float ref = ((float) This->StateBlock->renderstate[D3DRS_ALPHAREF]) / 255.0f;
2158 switch ((D3DCMPFUNC) Value) {
2159 case D3DCMP_NEVER: glParm = GL_NEVER; break;
2160 case D3DCMP_LESS: glParm = GL_LESS; break;
2161 case D3DCMP_EQUAL: glParm = GL_EQUAL; break;
2162 case D3DCMP_LESSEQUAL: glParm = GL_LEQUAL; break;
2163 case D3DCMP_GREATER: glParm = GL_GREATER; break;
2164 case D3DCMP_NOTEQUAL: glParm = GL_NOTEQUAL; break;
2165 case D3DCMP_GREATEREQUAL: glParm = GL_GEQUAL; break;
2166 case D3DCMP_ALWAYS: glParm = GL_ALWAYS; break;
2168 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2170 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2171 glAlphaFunc(glParm, ref);
2172 This->alphafunc = glParm;
2173 checkGLcall("glAlphaFunc");
2177 case D3DRS_ALPHAREF :
2179 int glParm = This->alphafunc;
2182 ref = ((float) Value) / 255.0f;
2183 TRACE("glAlphaFunc with Parm=%x, ref=%f\n", glParm, ref);
2184 glAlphaFunc(glParm, ref);
2185 checkGLcall("glAlphaFunc");
2189 case D3DRS_CLIPPLANEENABLE :
2190 case D3DRS_CLIPPING :
2192 /* Ensure we only do the changed clip planes */
2193 DWORD enable = 0xFFFFFFFF;
2194 DWORD disable = 0x00000000;
2196 /* If enabling / disabling all */
2197 if (State == D3DRS_CLIPPING) {
2199 enable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2202 disable = This->StateBlock->renderstate[D3DRS_CLIPPLANEENABLE];
2206 enable = Value & ~OldValue;
2207 disable = ~Value & OldValue;
2210 if (enable & D3DCLIPPLANE0) { glEnable(GL_CLIP_PLANE0); checkGLcall("glEnable(clip plane 0)"); }
2211 if (enable & D3DCLIPPLANE1) { glEnable(GL_CLIP_PLANE1); checkGLcall("glEnable(clip plane 1)"); }
2212 if (enable & D3DCLIPPLANE2) { glEnable(GL_CLIP_PLANE2); checkGLcall("glEnable(clip plane 2)"); }
2213 if (enable & D3DCLIPPLANE3) { glEnable(GL_CLIP_PLANE3); checkGLcall("glEnable(clip plane 3)"); }
2214 if (enable & D3DCLIPPLANE4) { glEnable(GL_CLIP_PLANE4); checkGLcall("glEnable(clip plane 4)"); }
2215 if (enable & D3DCLIPPLANE5) { glEnable(GL_CLIP_PLANE5); checkGLcall("glEnable(clip plane 5)"); }
2217 if (disable & D3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
2218 if (disable & D3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
2219 if (disable & D3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
2220 if (disable & D3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
2221 if (disable & D3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
2222 if (disable & D3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
2224 /** update clipping status */
2226 This->StateBlock->clip_status.ClipUnion = 0;
2227 This->StateBlock->clip_status.ClipIntersection = 0xFFFFFFFF;
2229 This->StateBlock->clip_status.ClipUnion = 0;
2230 This->StateBlock->clip_status.ClipIntersection = 0;
2235 case D3DRS_BLENDOP :
2237 int glParm = GL_FUNC_ADD;
2239 switch ((D3DBLENDOP) Value) {
2240 case D3DBLENDOP_ADD : glParm = GL_FUNC_ADD; break;
2241 case D3DBLENDOP_SUBTRACT : glParm = GL_FUNC_SUBTRACT; break;
2242 case D3DBLENDOP_REVSUBTRACT : glParm = GL_FUNC_REVERSE_SUBTRACT; break;
2243 case D3DBLENDOP_MIN : glParm = GL_MIN; break;
2244 case D3DBLENDOP_MAX : glParm = GL_MAX; break;
2246 FIXME("Unrecognized/Unhandled D3DBLENDOP value %ld\n", Value);
2248 TRACE("glBlendEquation(%x)\n", glParm);
2249 glBlendEquation(glParm);
2250 checkGLcall("glBlendEquation");
2254 case D3DRS_TEXTUREFACTOR :
2258 /* Note the texture color applies to all textures whereas
2259 GL_TEXTURE_ENV_COLOR applies to active only */
2261 D3DCOLORTOGLFLOAT4(Value, col);
2262 /* Set the default alpha blend color */
2263 glBlendColor(col[0], col[1], col[2], col[3]);
2264 checkGLcall("glBlendColor");
2266 /* And now the default texture color as well */
2267 for (i = 0; i < GL_LIMITS(textures); i++) {
2269 /* Note the D3DRS value applies to all textures, but GL has one
2270 per texture, so apply it now ready to be used! */
2271 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2272 #if defined(GL_VERSION_1_3)
2273 glActiveTexture(GL_TEXTURE0 + i);
2275 glActiveTextureARB(GL_TEXTURE0_ARB + i);
2277 checkGLcall("Activate texture.. to update const color");
2279 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
2282 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
2283 checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
2288 case D3DRS_SPECULARENABLE :
2290 /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
2291 and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
2292 specular color. This is wrong:
2293 Separate specular color means the specular colour is maintained separately, whereas
2294 single color means it is merged in. However in both cases they are being used to
2296 To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
2297 NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
2301 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &This->UpdateStateBlock->material.Specular);
2302 checkGLcall("glMaterialfv");
2303 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2304 glEnable(GL_COLOR_SUM_EXT);
2306 TRACE("Specular colors cannot be enabled in this version of opengl\n");
2308 checkGLcall("glEnable(GL_COLOR_SUM)");
2310 float black[4] = {0.0f, 0.0f, 0.0f, 0.0f};
2312 /* for the case of enabled lighting: */
2313 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
2314 checkGLcall("glMaterialfv");
2316 /* for the case of disabled lighting: */
2317 if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2318 glDisable(GL_COLOR_SUM_EXT);
2320 TRACE("Specular colors cannot be disabled in this version of opengl\n");
2322 checkGLcall("glDisable(GL_COLOR_SUM)");
2327 case D3DRS_STENCILENABLE :
2329 glEnable(GL_STENCIL_TEST);
2330 checkGLcall("glEnable GL_STENCIL_TEST");
2332 glDisable(GL_STENCIL_TEST);
2333 checkGLcall("glDisable GL_STENCIL_TEST");
2337 case D3DRS_STENCILFUNC :
2339 int glParm = GL_ALWAYS;
2340 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2341 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2343 switch ((D3DCMPFUNC) Value) {
2344 case D3DCMP_NEVER: glParm=GL_NEVER; break;
2345 case D3DCMP_LESS: glParm=GL_LESS; break;
2346 case D3DCMP_EQUAL: glParm=GL_EQUAL; break;
2347 case D3DCMP_LESSEQUAL: glParm=GL_LEQUAL; break;
2348 case D3DCMP_GREATER: glParm=GL_GREATER; break;
2349 case D3DCMP_NOTEQUAL: glParm=GL_NOTEQUAL; break;
2350 case D3DCMP_GREATEREQUAL: glParm=GL_GEQUAL; break;
2351 case D3DCMP_ALWAYS: glParm=GL_ALWAYS; break;
2353 FIXME("Unrecognized/Unhandled D3DCMPFUNC value %ld\n", Value);
2355 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2356 This->stencilfunc = glParm;
2357 glStencilFunc(glParm, ref, mask);
2358 checkGLcall("glStencilFunc");
2362 case D3DRS_STENCILREF :
2364 int glParm = This->stencilfunc;
2366 GLuint mask = This->StateBlock->renderstate[D3DRS_STENCILMASK];
2369 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2370 glStencilFunc(glParm, ref, mask);
2371 checkGLcall("glStencilFunc");
2375 case D3DRS_STENCILMASK :
2377 int glParm = This->stencilfunc;
2378 int ref = This->StateBlock->renderstate[D3DRS_STENCILREF];
2379 GLuint mask = Value;
2381 TRACE("glStencilFunc with Parm=%x, ref=%d, mask=%x\n", glParm, ref, mask);
2382 glStencilFunc(glParm, ref, mask);
2383 checkGLcall("glStencilFunc");
2387 case D3DRS_STENCILFAIL :
2393 fail = StencilOp(Value);
2394 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2395 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2396 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2397 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2399 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2400 glStencilOp(fail, zfail, zpass);
2401 checkGLcall("glStencilOp(fail, zfail, zpass);");
2404 case D3DRS_STENCILZFAIL :
2410 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2411 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2412 glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);
2413 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &zpass);");
2414 zfail = StencilOp(Value);
2416 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2417 glStencilOp(fail, zfail, zpass);
2418 checkGLcall("glStencilOp(fail, zfail, zpass);");
2421 case D3DRS_STENCILPASS :
2427 glGetIntegerv(GL_STENCIL_FAIL, &fail);
2428 checkGLcall("glGetIntegerv(GL_STENCIL_FAIL, &fail);");
2429 zpass = StencilOp(Value);
2430 glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);
2431 checkGLcall("glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &zfail);");
2433 TRACE("StencilOp fail=%x, zfail=%x, zpass=%x\n", fail, zfail, zpass);
2434 glStencilOp(fail, zfail, zpass);
2435 checkGLcall("glStencilOp(fail, zfail, zpass);");
2439 case D3DRS_STENCILWRITEMASK :
2441 glStencilMask(Value);
2442 TRACE("glStencilMask(%lu)\n", Value);
2443 checkGLcall("glStencilMask");
2447 case D3DRS_FOGENABLE :
2449 if (Value/* && This->StateBlock->renderstate[D3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
2451 checkGLcall("glEnable GL_FOG");
2454 checkGLcall("glDisable GL_FOG");
2459 case D3DRS_RANGEFOGENABLE :
2462 TRACE("Enabled RANGEFOG");
2464 TRACE("Disabled RANGEFOG");
2469 case D3DRS_FOGCOLOR :
2472 D3DCOLORTOGLFLOAT4(Value, col);
2473 /* Set the default alpha blend color */
2474 glFogfv(GL_FOG_COLOR, &col[0]);
2475 checkGLcall("glFog GL_FOG_COLOR");
2479 case D3DRS_FOGTABLEMODE :
2481 glHint(GL_FOG_HINT, GL_NICEST);
2483 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2484 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2485 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2486 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2488 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2490 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2491 glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
2496 case D3DRS_FOGVERTEXMODE :
2498 glHint(GL_FOG_HINT, GL_FASTEST);
2500 case D3DFOG_NONE: /* I don't know what to do here */ checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2501 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
2502 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
2503 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
2505 FIXME("Unsupported Value(%lu) for D3DRS_FOGTABLEMODE!\n", Value);
2507 if (GL_SUPPORT(NV_FOG_DISTANCE)) {
2508 glFogi(GL_FOG_DISTANCE_MODE_NV, This->StateBlock->renderstate[D3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
2513 case D3DRS_FOGSTART :
2516 glFogfv(GL_FOG_START, &tmpvalue.f);
2517 checkGLcall("glFogf(GL_FOG_START, (float) Value)");
2518 TRACE("Fog Start == %f\n", tmpvalue.f);
2525 glFogfv(GL_FOG_END, &tmpvalue.f);
2526 checkGLcall("glFogf(GL_FOG_END, (float) Value)");
2527 TRACE("Fog End == %f\n", tmpvalue.f);
2531 case D3DRS_FOGDENSITY :
2534 glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
2535 checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
2539 case D3DRS_VERTEXBLEND :
2541 This->UpdateStateBlock->vertex_blend = (D3DVERTEXBLENDFLAGS) Value;
2542 TRACE("Vertex Blending state to %ld\n", Value);
2546 case D3DRS_TWEENFACTOR :
2549 This->UpdateStateBlock->tween_factor = tmpvalue.f;
2550 TRACE("Vertex Blending Tween Factor to %f\n", This->UpdateStateBlock->tween_factor);
2554 case D3DRS_INDEXEDVERTEXBLENDENABLE :
2556 TRACE("Indexed Vertex Blend Enable to %ul\n", (BOOL) Value);
2560 case D3DRS_COLORVERTEX :
2561 case D3DRS_DIFFUSEMATERIALSOURCE :
2562 case D3DRS_SPECULARMATERIALSOURCE :
2563 case D3DRS_AMBIENTMATERIALSOURCE :
2564 case D3DRS_EMISSIVEMATERIALSOURCE :
2566 GLenum Parm = GL_AMBIENT_AND_DIFFUSE;
2568 if (This->StateBlock->renderstate[D3DRS_COLORVERTEX]) {
2569 TRACE("diff %ld, amb %ld, emis %ld, spec %ld\n",
2570 This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE],
2571 This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE],
2572 This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE],
2573 This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE]);
2575 if (This->StateBlock->renderstate[D3DRS_DIFFUSEMATERIALSOURCE] == D3DMCS_COLOR1) {
2576 if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2577 Parm = GL_AMBIENT_AND_DIFFUSE;
2581 } else if (This->StateBlock->renderstate[D3DRS_AMBIENTMATERIALSOURCE] == D3DMCS_COLOR1) {
2583 } else if (This->StateBlock->renderstate[D3DRS_EMISSIVEMATERIALSOURCE] == D3DMCS_COLOR1) {
2585 } else if (This->StateBlock->renderstate[D3DRS_SPECULARMATERIALSOURCE] == D3DMCS_COLOR1) {
2592 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2594 This->tracking_color = NEEDS_TRACKING;
2595 This->tracking_parm = Parm;
2599 if (This->tracking_color != DISABLED_TRACKING) This->tracking_color = NEEDS_DISABLE;
2604 case D3DRS_LINEPATTERN :
2610 tmppattern.d = Value;
2612 TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2614 if (tmppattern.lp.wRepeatFactor) {
2615 glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
2616 checkGLcall("glLineStipple(repeat, linepattern)");
2617 glEnable(GL_LINE_STIPPLE);
2618 checkGLcall("glEnable(GL_LINE_STIPPLE);");
2620 glDisable(GL_LINE_STIPPLE);
2621 checkGLcall("glDisable(GL_LINE_STIPPLE);");
2630 TRACE("ZBias value %f\n", tmpvalue.f);
2631 glPolygonOffset(0, -tmpvalue.f);
2632 checkGLcall("glPolygonOffset(0, -Value)");
2633 glEnable(GL_POLYGON_OFFSET_FILL);
2634 checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
2635 glEnable(GL_POLYGON_OFFSET_LINE);
2636 checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
2637 glEnable(GL_POLYGON_OFFSET_POINT);
2638 checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
2640 glDisable(GL_POLYGON_OFFSET_FILL);
2641 checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
2642 glDisable(GL_POLYGON_OFFSET_LINE);
2643 checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
2644 glDisable(GL_POLYGON_OFFSET_POINT);
2645 checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
2650 case D3DRS_NORMALIZENORMALS :
2652 glEnable(GL_NORMALIZE);
2653 checkGLcall("glEnable(GL_NORMALIZE);");
2655 glDisable(GL_NORMALIZE);
2656 checkGLcall("glDisable(GL_NORMALIZE);");
2660 case D3DRS_POINTSIZE :
2662 TRACE("Set point size to %f\n", tmpvalue.f);
2663 glPointSize(tmpvalue.f);
2664 checkGLcall("glPointSize(...);");
2667 case D3DRS_POINTSIZE_MIN :
2668 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2670 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, tmpvalue.f);
2671 checkGLcall("glPointParameterfEXT(...);");
2673 FIXME("D3DRS_POINTSIZE_MIN not supported on this opengl\n");
2677 case D3DRS_POINTSIZE_MAX :
2678 if (GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2680 GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, tmpvalue.f);
2681 checkGLcall("glPointParameterfEXT(...);");
2683 FIXME("D3DRS_POINTSIZE_MAX not supported on this opengl\n");
2687 case D3DRS_POINTSCALE_A :
2688 case D3DRS_POINTSCALE_B :
2689 case D3DRS_POINTSCALE_C :
2690 case D3DRS_POINTSCALEENABLE :
2693 * POINTSCALEENABLE controls how point size value is treated. If set to
2694 * true, the point size is scaled with respect to height of viewport.
2695 * When set to false point size is in pixels.
2697 * http://msdn.microsoft.com/library/en-us/directx9_c/point_sprites.asp
2700 /* Default values */
2701 GLfloat att[3] = {1.0f, 0.0f, 0.0f};
2704 * Minium valid point size for OpenGL is 1.0f. For Direct3D it is 0.0f.
2705 * This means that OpenGL will clamp really small point sizes to 1.0f.
2706 * To correct for this we need to multiply by the scale factor when sizes
2707 * are less than 1.0f. scale_factor = 1.0f / point_size.
2709 GLfloat pointSize = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSIZE]);
2710 GLfloat scaleFactor;
2711 if(pointSize < 1.0f) {
2712 scaleFactor = pointSize * pointSize;
2717 if(This->StateBlock->renderstate[D3DRS_POINTSCALEENABLE]) {
2718 att[0] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_A]) /
2719 (This->StateBlock->viewport.Height * This->StateBlock->viewport.Height * scaleFactor);
2720 att[1] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_B]) /
2721 (This->StateBlock->viewport.Height * This->StateBlock->viewport.Height * scaleFactor);
2722 att[2] = *((float*)&This->StateBlock->renderstate[D3DRS_POINTSCALE_C]) /
2723 (This->StateBlock->viewport.Height * This->StateBlock->viewport.Height * scaleFactor);
2726 if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
2727 GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
2728 checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...");
2730 else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
2731 GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
2732 checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...");
2735 TRACE("POINT_PARAMETERS not supported in this version of opengl\n");
2739 case D3DRS_COLORWRITEENABLE :
2741 TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
2742 Value & D3DCOLORWRITEENABLE_RED ? 1 : 0,
2743 Value & D3DCOLORWRITEENABLE_GREEN ? 1 : 0,
2744 Value & D3DCOLORWRITEENABLE_BLUE ? 1 : 0,
2745 Value & D3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
2746 glColorMask(Value & D3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
2747 Value & D3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
2748 Value & D3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
2749 Value & D3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
2750 checkGLcall("glColorMask(...)");
2754 case D3DRS_LOCALVIEWER :
2756 GLint state = (Value) ? 1 : 0;
2757 TRACE("Local Viewer Enable to %ul\n", (BOOL) Value);
2758 glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, state);
2762 case D3DRS_LASTPIXEL :
2765 TRACE("Last Pixel Drawing Enabled\n");
2767 FIXME("Last Pixel Drawing Disabled, not handled yet\n");
2772 case D3DRS_SOFTWAREVERTEXPROCESSING :
2775 TRACE("Software Processing Enabled\n");
2777 TRACE("Software Processing Disabled\n");
2782 /** not supported */
2783 case D3DRS_ZVISIBLE :
2786 return D3DERR_INVALIDCALL;
2789 /* Unhandled yet...! */
2790 case D3DRS_EDGEANTIALIAS :
2793 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2795 checkGLcall("glEnable GL_BLEND");
2796 glEnable(GL_LINE_SMOOTH);
2797 checkGLcall("glEnable Gl_LINE_SMOOTH");
2799 glDisable(GL_BLEND);
2800 checkGLcall("glDisable GL_BLEND");
2801 glDisable(GL_LINE_SMOOTH);
2802 checkGLcall("glDisable GL_LINE_SMOOTH");
2815 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2818 case D3DRS_POINTSPRITEENABLE :
2820 if (!GL_SUPPORT(ARB_POINT_SPRITE)) {
2821 TRACE("Point sprites not supported\n");
2826 * Point sprites are always enabled. Value controls texture coordinate
2827 * replacement mode. Must be set true for point sprites to use
2830 glEnable(GL_POINT_SPRITE_ARB);
2831 checkGLcall("glEnable GL_POINT_SPRITE_ARB");
2834 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE);
2836 glTexEnvf(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, FALSE);
2840 case D3DRS_MULTISAMPLEANTIALIAS :
2842 if (!GL_SUPPORT(ARB_MULTISAMPLE)) {
2843 TRACE("Multisample antialiasing not supported\n");
2848 glEnable(GL_MULTISAMPLE_ARB);
2849 checkGLcall("glEnable GL_MULTISAMPLE_ARB");
2851 glDisable(GL_MULTISAMPLE_ARB);
2852 checkGLcall("glDisable GL_MULTISAMPLE_ARB");
2856 case D3DRS_MULTISAMPLEMASK :
2857 case D3DRS_PATCHEDGESTYLE :
2858 case D3DRS_PATCHSEGMENTS :
2859 case D3DRS_DEBUGMONITORTOKEN :
2860 case D3DRS_POSITIONORDER :
2861 case D3DRS_NORMALORDER :
2862 /*Put back later: FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value); */
2863 FIXME("(%p)->(%d,%ld) not handled yet\n", This, State, Value);
2866 FIXME("(%p)->(%d,%ld) unrecognized\n", This, State, Value);
2873 HRESULT WINAPI IDirect3DDevice8Impl_GetRenderState(LPDIRECT3DDEVICE8 iface, D3DRENDERSTATETYPE State,DWORD* pValue) {
2874 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2875 TRACE("(%p) for State %d = %ld\n", This, State, This->UpdateStateBlock->renderstate[State]);
2876 *pValue = This->StateBlock->renderstate[State];
2879 HRESULT WINAPI IDirect3DDevice8Impl_BeginStateBlock(LPDIRECT3DDEVICE8 iface) {
2880 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2882 TRACE("(%p)\n", This);
2884 return IDirect3DDeviceImpl_BeginStateBlock(This);
2886 HRESULT WINAPI IDirect3DDevice8Impl_EndStateBlock(LPDIRECT3DDEVICE8 iface, DWORD* pToken) {
2887 IDirect3DStateBlockImpl* pSB;
2888 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2891 TRACE("(%p)\n", This);
2893 res = IDirect3DDeviceImpl_EndStateBlock(This, &pSB);
2894 *pToken = (DWORD) pSB;
2898 HRESULT WINAPI IDirect3DDevice8Impl_ApplyStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2899 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2900 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2902 TRACE("(%p)\n", This);
2904 return IDirect3DDeviceImpl_ApplyStateBlock(This, pSB);
2907 HRESULT WINAPI IDirect3DDevice8Impl_CaptureStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2908 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2909 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2911 TRACE("(%p)\n", This);
2913 return IDirect3DDeviceImpl_CaptureStateBlock(This, pSB);
2915 HRESULT WINAPI IDirect3DDevice8Impl_DeleteStateBlock(LPDIRECT3DDEVICE8 iface, DWORD Token) {
2916 IDirect3DStateBlockImpl* pSB = (IDirect3DStateBlockImpl*) Token;
2917 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2919 TRACE("(%p)\n", This);
2921 return IDirect3DDeviceImpl_DeleteStateBlock(This, pSB);
2924 HRESULT WINAPI IDirect3DDevice8Impl_CreateStateBlock(LPDIRECT3DDEVICE8 iface, D3DSTATEBLOCKTYPE Type, DWORD* pToken) {
2925 IDirect3DStateBlockImpl* pSB;
2926 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2929 TRACE("(%p) : for type %d\n", This, Type);
2931 res = IDirect3DDeviceImpl_CreateStateBlock(This, Type, &pSB);
2932 *pToken = (DWORD) pSB;
2936 HRESULT WINAPI IDirect3DDevice8Impl_SetClipStatus(LPDIRECT3DDEVICE8 iface, CONST D3DCLIPSTATUS8* pClipStatus) {
2937 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2938 FIXME("(%p) : stub\n", This);
2939 if (NULL == pClipStatus) {
2940 return D3DERR_INVALIDCALL;
2942 This->UpdateStateBlock->clip_status.ClipUnion = pClipStatus->ClipUnion;
2943 This->UpdateStateBlock->clip_status.ClipIntersection = pClipStatus->ClipIntersection;
2946 HRESULT WINAPI IDirect3DDevice8Impl_GetClipStatus(LPDIRECT3DDEVICE8 iface, D3DCLIPSTATUS8* pClipStatus) {
2947 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2948 FIXME("(%p) : stub\n", This);
2949 if (NULL == pClipStatus) {
2950 return D3DERR_INVALIDCALL;
2952 pClipStatus->ClipUnion = This->UpdateStateBlock->clip_status.ClipUnion;
2953 pClipStatus->ClipIntersection = This->UpdateStateBlock->clip_status.ClipIntersection;
2956 HRESULT WINAPI IDirect3DDevice8Impl_GetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage,IDirect3DBaseTexture8** ppTexture) {
2957 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2958 TRACE("(%p) : returning %p for stage %ld\n", This, This->UpdateStateBlock->textures[Stage], Stage);
2959 *ppTexture = (LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage];
2961 IDirect3DBaseTexture8Impl_AddRef(*ppTexture);
2964 HRESULT WINAPI IDirect3DDevice8Impl_SetTexture(LPDIRECT3DDEVICE8 iface, DWORD Stage, IDirect3DBaseTexture8* pTexture) {
2966 IDirect3DBaseTexture8 *oldTxt;
2967 BOOL reapplyStates = TRUE;
2968 INT oldTextureDimensions = -1;
2969 DWORD reapplyFlags = 0;
2971 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
2972 D3DRESOURCETYPE textureType;
2974 oldTxt = This->UpdateStateBlock->textures[Stage];
2975 TRACE("(%p) : Stage(%ld), Texture (%p)\n", This, Stage, pTexture);
2977 /* Reject invalid texture units */
2978 if (Stage >= GL_LIMITS(textures)) {
2979 TRACE("Attempt to access invalid texture rejected\n");
2980 return D3DERR_INVALIDCALL;
2983 This->UpdateStateBlock->Set.textures[Stage] = TRUE;
2984 This->UpdateStateBlock->Changed.textures[Stage] = TRUE;
2985 This->UpdateStateBlock->textures[Stage] = pTexture;
2987 /* Handle recording of state blocks */
2988 if (This->isRecordingState) {
2989 TRACE("Recording... not performing anything\n");
2993 oldTextureDimensions = This->UpdateStateBlock->textureDimensions[Stage];
2996 /* Make appropriate texture active */
2997 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
2998 #if defined(GL_VERSION_1_3)
2999 glActiveTexture(GL_TEXTURE0 + Stage);
3000 checkGLcall("glActiveTexture");
3002 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3003 checkGLcall("glActiveTextureARB");
3005 } else if (Stage>0) {
3006 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3009 /* Decrement the count of the previous texture */
3010 if (NULL != oldTxt) {
3011 IDirect3DBaseTexture8Impl_Release(oldTxt);
3014 if (NULL != pTexture) {
3015 IDirect3DBaseTexture8Impl_AddRef((LPDIRECT3DBASETEXTURE8) This->UpdateStateBlock->textures[Stage]);
3017 /* Now setup the texture appropraitly */
3018 textureType = IDirect3DBaseTexture8Impl_GetType(pTexture);
3019 if (textureType == D3DRTYPE_TEXTURE) {
3020 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3021 TRACE("Skipping setting texture as old == new\n");
3022 reapplyStates = FALSE;
3024 /* Standard 2D texture */
3025 TRACE("Standard 2d texture\n");
3026 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_2D;
3028 /* Load up the texture now */
3029 IDirect3DTexture8Impl_PreLoad((LPDIRECT3DTEXTURE8) pTexture);
3031 } else if (textureType == D3DRTYPE_VOLUMETEXTURE) {
3032 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3033 TRACE("Skipping setting texture as old == new\n");
3034 reapplyStates = FALSE;
3036 /* Standard 3D (volume) texture */
3037 TRACE("Standard 3d texture\n");
3038 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_3D;
3040 /* Load up the texture now */
3041 IDirect3DVolumeTexture8Impl_PreLoad((LPDIRECT3DVOLUMETEXTURE8) pTexture);
3043 } else if (textureType == D3DRTYPE_CUBETEXTURE) {
3044 if (oldTxt == pTexture && IDirect3DBaseTexture8Impl_IsDirty(pTexture)) {
3045 TRACE("Skipping setting texture as old == new\n");
3046 reapplyStates = FALSE;
3048 /* Standard Cube texture */
3049 TRACE("Standard Cube texture\n");
3050 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_CUBE_MAP_ARB;
3052 /* Load up the texture now */
3053 IDirect3DCubeTexture8Impl_PreLoad((LPDIRECT3DCUBETEXTURE8) pTexture);
3056 FIXME("(%p) : Incorrect type for a texture : (%d,%s)\n", This, textureType, debug_d3dressourcetype(textureType));
3059 TRACE("Setting to no texture (ie default texture)\n");
3060 This->UpdateStateBlock->textureDimensions[Stage] = GL_TEXTURE_1D;
3061 glBindTexture(GL_TEXTURE_1D, This->dummyTextureName[Stage]);
3062 checkGLcall("glBindTexture");
3063 TRACE("Bound dummy Texture to stage %ld (gl name %d)\n", Stage, This->dummyTextureName[Stage]);
3066 /* Disable the old texture binding and enable the new one (unless operations are disabled) */
3067 if (oldTextureDimensions != This->UpdateStateBlock->textureDimensions[Stage]) {
3068 glDisable(oldTextureDimensions);
3069 checkGLcall("Disable oldTextureDimensions");
3070 if (This->StateBlock->texture_state[Stage][D3DTSS_COLOROP] != D3DTOP_DISABLE) {
3071 glEnable(This->UpdateStateBlock->textureDimensions[Stage]);
3072 checkGLcall("glEnable new texture dimensions");
3075 /* If Alpha arg1 is texture then handle the special case when there changes between a
3076 texture and no texture - See comments in set_tex_op */
3077 if ((This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1] == D3DTA_TEXTURE) &&
3078 (((oldTxt == NULL) && (pTexture != NULL)) || ((pTexture == NULL) && (oldTxt != NULL))))
3080 reapplyFlags |= REAPPLY_ALPHAOP;
3085 /* Even if the texture has been set to null, reapply the stages as a null texture to directx requires
3086 a dummy texture in opengl, and we always need to ensure the current view of the TextureStates apply */
3087 if (reapplyStates) {
3088 setupTextureStates(iface, Stage, reapplyFlags);
3096 HRESULT WINAPI IDirect3DDevice8Impl_GetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage,D3DTEXTURESTAGESTATETYPE Type,DWORD* pValue) {
3097 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3098 TRACE("(%p) : requesting Stage %ld, Type %d getting %ld\n", This, Stage, Type, This->UpdateStateBlock->texture_state[Stage][Type]);
3099 *pValue = This->UpdateStateBlock->texture_state[Stage][Type];
3103 HRESULT WINAPI IDirect3DDevice8Impl_SetTextureStageState(LPDIRECT3DDEVICE8 iface, DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) {
3104 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3110 /* FIXME: Handle 3d textures? What if TSS value set before set texture? Need to reapply all values? */
3112 TRACE("(%p) : Stage=%ld, Type=%s(%d), Value=%ld\n", This, Stage, debug_d3dtexturestate(Type), Type, Value);
3114 /* Reject invalid texture units */
3115 if (Stage >= GL_LIMITS(textures)) {
3116 TRACE("Attempt to access invalid texture rejected\n");
3117 return D3DERR_INVALIDCALL;
3120 This->UpdateStateBlock->Changed.texture_state[Stage][Type] = TRUE;
3121 This->UpdateStateBlock->Set.texture_state[Stage][Type] = TRUE;
3122 This->UpdateStateBlock->texture_state[Stage][Type] = Value;
3124 /* Handle recording of state blocks */
3125 if (This->isRecordingState) {
3126 TRACE("Recording... not performing anything\n");
3132 /* Make appropriate texture active */
3133 VTRACE(("Activating appropriate texture state %ld\n", Stage));
3134 if (GL_SUPPORT(ARB_MULTITEXTURE)) {
3135 #if defined(GL_VERSION_1_3)
3136 glActiveTexture(GL_TEXTURE0 + Stage);
3137 vcheckGLcall("glActiveTexture");
3139 glActiveTextureARB(GL_TEXTURE0_ARB + Stage);
3140 vcheckGLcall("glActiveTextureARB");
3142 } else if (Stage > 0) {
3143 FIXME("Program using multiple concurrent textures which this opengl implementation doesn't support\n");
3148 case D3DTSS_MINFILTER :
3149 case D3DTSS_MIPFILTER :
3151 DWORD ValueMIN = This->StateBlock->texture_state[Stage][D3DTSS_MINFILTER];
3152 DWORD ValueMIP = This->StateBlock->texture_state[Stage][D3DTSS_MIPFILTER];
3153 GLint realVal = GL_LINEAR;
3155 if (ValueMIN == D3DTEXF_NONE) {
3156 /* Doesn't really make sense - Windows just seems to disable
3157 mipmapping when this occurs */
3158 FIXME("Odd - minfilter of none, just disabling mipmaps\n");
3159 realVal = GL_LINEAR;
3160 } else if (ValueMIN == D3DTEXF_POINT) {
3162 if (ValueMIP == D3DTEXF_NONE) {
3163 realVal = GL_NEAREST;
3164 } else if (ValueMIP == D3DTEXF_POINT) {
3165 realVal = GL_NEAREST_MIPMAP_NEAREST;
3166 } else if (ValueMIP == D3DTEXF_LINEAR) {
3167 realVal = GL_NEAREST_MIPMAP_LINEAR;
3169 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3170 realVal = GL_NEAREST;
3172 } else if (ValueMIN == D3DTEXF_LINEAR) {
3174 if (ValueMIP == D3DTEXF_NONE) {
3175 realVal = GL_LINEAR;
3176 } else if (ValueMIP == D3DTEXF_POINT) {
3177 realVal = GL_LINEAR_MIPMAP_NEAREST;
3178 } else if (ValueMIP == D3DTEXF_LINEAR) {
3179 realVal = GL_LINEAR_MIPMAP_LINEAR;
3181 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3182 realVal = GL_LINEAR;
3184 } else if (ValueMIN == D3DTEXF_ANISOTROPIC) {
3185 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3186 if (ValueMIP == D3DTEXF_NONE) {
3187 realVal = GL_LINEAR_MIPMAP_LINEAR;
3188 } else if (ValueMIP == D3DTEXF_POINT) {
3189 realVal = GL_LINEAR_MIPMAP_NEAREST;
3190 } else if (ValueMIP == D3DTEXF_LINEAR) {
3191 realVal = GL_LINEAR_MIPMAP_LINEAR;
3193 FIXME("Unhandled D3DTSS_MIPFILTER value of %ld\n", ValueMIP);
3194 realVal = GL_LINEAR;
3197 WARN("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MINFILTER. But not supported by OpenGL driver\n");
3198 realVal = GL_LINEAR;
3201 FIXME("Unhandled D3DTSS_MINFILTER value of %ld\n", ValueMIN);
3202 realVal = GL_LINEAR_MIPMAP_LINEAR;
3205 TRACE("ValueMIN=%ld, ValueMIP=%ld, setting MINFILTER to %x\n", ValueMIN, ValueMIP, realVal);
3206 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MIN_FILTER, realVal);
3207 checkGLcall("glTexParameter GL_TEXTURE_MIN_FILTER, ...");
3209 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3211 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMIN) {
3212 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3213 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3214 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3215 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3220 case D3DTSS_MAGFILTER :
3222 DWORD ValueMAG = This->StateBlock->texture_state[Stage][D3DTSS_MAGFILTER];
3223 GLint realVal = GL_NEAREST;
3225 if (ValueMAG == D3DTEXF_POINT) {
3226 realVal = GL_NEAREST;
3227 } else if (ValueMAG == D3DTEXF_LINEAR) {
3228 realVal = GL_LINEAR;
3229 } else if (ValueMAG == D3DTEXF_ANISOTROPIC) {
3230 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3231 realVal = GL_LINEAR;
3233 FIXME("Trying to use ANISOTROPIC_FILTERING for D3DTSS_MAGFILTER. But not supported by current OpenGL driver\n");
3234 realVal = GL_NEAREST;
3237 FIXME("Unhandled D3DTSS_MAGFILTER value of %ld\n", ValueMAG);
3238 realVal = GL_NEAREST;
3240 TRACE("ValueMAG=%ld setting MAGFILTER to %x\n", ValueMAG, realVal);
3241 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_MAG_FILTER, realVal);
3242 checkGLcall("glTexParameter GL_TEXTURE_MAG_FILTER, ...");
3244 * if we juste choose to use ANISOTROPIC filtering, refresh openGL state
3246 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC) && D3DTEXF_ANISOTROPIC == ValueMAG) {
3247 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3248 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3249 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3250 checkGLcall("glTexParameter GL_TEXTURE_MAX_ANISOTROPY_EXT, ...");
3255 case D3DTSS_MAXMIPLEVEL :
3258 * Not really the same, but the more apprioprate than nothing
3260 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3261 GL_TEXTURE_BASE_LEVEL,
3262 This->StateBlock->texture_state[Stage][D3DTSS_MAXMIPLEVEL]);
3263 checkGLcall("glTexParameteri GL_TEXTURE_BASE_LEVEL ...");
3267 case D3DTSS_MAXANISOTROPY :
3269 if (GL_SUPPORT(EXT_TEXTURE_FILTER_ANISOTROPIC)) {
3270 glTexParameteri(This->StateBlock->textureDimensions[Stage],
3271 GL_TEXTURE_MAX_ANISOTROPY_EXT,
3272 This->StateBlock->texture_state[Stage][D3DTSS_MAXANISOTROPY]);
3273 checkGLcall("glTexParameteri GL_TEXTURE_MAX_ANISOTROPY_EXT ...");
3278 case D3DTSS_MIPMAPLODBIAS :
3280 if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3282 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3283 GL_TEXTURE_LOD_BIAS_EXT,
3285 checkGLcall("glTexEnvi GL_TEXTURE_LOD_BIAS_EXT ...");
3290 case D3DTSS_ALPHAOP :
3291 case D3DTSS_COLOROP :
3294 if ((Value == D3DTOP_DISABLE) && (Type == D3DTSS_COLOROP)) {
3295 /* TODO: Disable by making this and all later levels disabled */
3296 glDisable(GL_TEXTURE_1D);
3297 checkGLcall("Disable GL_TEXTURE_1D");
3298 glDisable(GL_TEXTURE_2D);
3299 checkGLcall("Disable GL_TEXTURE_2D");
3300 glDisable(GL_TEXTURE_3D);
3301 checkGLcall("Disable GL_TEXTURE_3D");
3302 break; /* Don't bother setting the texture operations */
3304 /* Enable only the appropriate texture dimension */
3305 if (Type == D3DTSS_COLOROP) {
3306 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_1D) {
3307 glEnable(GL_TEXTURE_1D);
3308 checkGLcall("Enable GL_TEXTURE_1D");
3310 glDisable(GL_TEXTURE_1D);
3311 checkGLcall("Disable GL_TEXTURE_1D");
3313 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_2D) {
3314 if (GL_SUPPORT(NV_TEXTURE_SHADER) && This->texture_shader_active) {
3315 glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_2D);
3316 checkGLcall("Enable GL_TEXTURE_2D");
3318 glEnable(GL_TEXTURE_2D);
3319 checkGLcall("Enable GL_TEXTURE_2D");
3322 glDisable(GL_TEXTURE_2D);
3323 checkGLcall("Disable GL_TEXTURE_2D");
3325 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_3D) {
3326 glEnable(GL_TEXTURE_3D);
3327 checkGLcall("Enable GL_TEXTURE_3D");
3329 glDisable(GL_TEXTURE_3D);
3330 checkGLcall("Disable GL_TEXTURE_3D");
3332 if (This->StateBlock->textureDimensions[Stage] == GL_TEXTURE_CUBE_MAP_ARB) {
3333 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3334 checkGLcall("Enable GL_TEXTURE_CUBE_MAP");
3336 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3337 checkGLcall("Disable GL_TEXTURE_CUBE_MAP");
3341 /* Drop through... (Except disable case) */
3342 case D3DTSS_COLORARG0 :
3343 case D3DTSS_COLORARG1 :
3344 case D3DTSS_COLORARG2 :
3345 case D3DTSS_ALPHAARG0 :
3346 case D3DTSS_ALPHAARG1 :
3347 case D3DTSS_ALPHAARG2 :
3349 BOOL isAlphaArg = (Type == D3DTSS_ALPHAOP || Type == D3DTSS_ALPHAARG1 ||
3350 Type == D3DTSS_ALPHAARG2 || Type == D3DTSS_ALPHAARG0);
3352 set_tex_op(iface, TRUE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_ALPHAOP],
3353 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG1],
3354 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG2],
3355 This->StateBlock->texture_state[Stage][D3DTSS_ALPHAARG0]);
3357 set_tex_op(iface, FALSE, Stage, This->StateBlock->texture_state[Stage][D3DTSS_COLOROP],
3358 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG1],
3359 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG2],
3360 This->StateBlock->texture_state[Stage][D3DTSS_COLORARG0]);
3366 case D3DTSS_ADDRESSU :
3367 case D3DTSS_ADDRESSV :
3368 case D3DTSS_ADDRESSW :
3370 GLint wrapParm = GL_REPEAT;
3373 case D3DTADDRESS_WRAP: wrapParm = GL_REPEAT; break;
3374 case D3DTADDRESS_CLAMP: wrapParm = GL_CLAMP_TO_EDGE; break;
3375 case D3DTADDRESS_BORDER:
3377 if (GL_SUPPORT(ARB_TEXTURE_BORDER_CLAMP)) {
3378 wrapParm = GL_CLAMP_TO_BORDER_ARB;
3380 /* FIXME: Not right, but better */
3381 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3382 wrapParm = GL_REPEAT;
3386 case D3DTADDRESS_MIRROR:
3388 if (GL_SUPPORT(ARB_TEXTURE_MIRRORED_REPEAT)) {
3389 wrapParm = GL_MIRRORED_REPEAT_ARB;
3391 /* Unsupported in OpenGL pre-1.4 */
3392 FIXME("Unsupported D3DTADDRESS_MIRROR (needs GL_ARB_texture_mirrored_repeat) state %d\n", Type);
3393 wrapParm = GL_REPEAT;
3397 case D3DTADDRESS_MIRRORONCE:
3399 if (GL_SUPPORT(ATI_TEXTURE_MIRROR_ONCE)) {
3400 wrapParm = GL_MIRROR_CLAMP_TO_EDGE_ATI;
3402 FIXME("Unsupported D3DTADDRESS_MIRRORONCE (needs GL_ATI_texture_mirror_once) state %d\n", Type);
3403 wrapParm = GL_REPEAT;
3409 FIXME("Unrecognized or unsupported D3DTADDRESS_* value %ld, state %d\n", Value, Type);
3410 wrapParm = GL_REPEAT;
3414 case D3DTSS_ADDRESSU:
3415 TRACE("Setting WRAP_S to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3416 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_S, wrapParm);
3417 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_S, wrapParm)");
3419 case D3DTSS_ADDRESSV:
3420 TRACE("Setting WRAP_T to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3421 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_T, wrapParm);
3422 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_T, wrapParm)");
3424 case D3DTSS_ADDRESSW:
3425 TRACE("Setting WRAP_R to %d for %x\n", wrapParm, This->StateBlock->textureDimensions[Stage]);
3426 glTexParameteri(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_WRAP_R, wrapParm);
3427 checkGLcall("glTexParameteri(..., GL_TEXTURE_WRAP_R, wrapParm)");
3430 break; /** stupic compilator */
3435 case D3DTSS_BORDERCOLOR :
3438 D3DCOLORTOGLFLOAT4(Value, col);
3439 TRACE("Setting border color for %x to %lx\n", This->StateBlock->textureDimensions[Stage], Value);
3440 glTexParameterfv(This->StateBlock->textureDimensions[Stage], GL_TEXTURE_BORDER_COLOR, &col[0]);
3441 checkGLcall("glTexParameteri(..., GL_TEXTURE_BORDER_COLOR, ...)");
3445 case D3DTSS_TEXCOORDINDEX :
3447 /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive */
3449 /* FIXME: From MSDN: The D3DTSS_TCI_* flags are mutually exclusive. If you include
3450 one flag, you can still specify an index value, which the system uses to
3451 determine the texture wrapping mode.
3452 eg. SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3453 means use the vertex position (camera-space) as the input texture coordinates
3454 for this texture stage, and the wrap mode set in the D3DRS_WRAP1 render
3455 state. We do not (yet) support the D3DRENDERSTATE_WRAPx values, nor tie them up
3456 to the TEXCOORDINDEX value */
3459 * Be careful the value of the mask 0xF0000 come from d3d8types.h infos
3461 switch (Value & 0xFFFF0000) {
3462 case D3DTSS_TCI_PASSTHRU:
3463 /*Use the specified texture coordinates contained within the vertex format. This value resolves to zero.*/
3464 glDisable(GL_TEXTURE_GEN_S);
3465 glDisable(GL_TEXTURE_GEN_T);
3466 glDisable(GL_TEXTURE_GEN_R);
3467 checkGLcall("glDisable(GL_TEXTURE_GEN_S,T,R)");
3470 case D3DTSS_TCI_CAMERASPACEPOSITION:
3471 /* CameraSpacePosition means use the vertex position, transformed to camera space,
3472 as the input texture coordinates for this stage's texture transformation. This
3473 equates roughly to EYE_LINEAR */
3475 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3476 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3477 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3478 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3479 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3481 glMatrixMode(GL_MODELVIEW);
3484 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3485 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3486 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3487 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3490 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set GL_TEXTURE_GEN_x and GL_x, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR\n");
3491 glEnable(GL_TEXTURE_GEN_S);
3492 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3493 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3494 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3495 glEnable(GL_TEXTURE_GEN_T);
3496 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3497 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3498 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3499 glEnable(GL_TEXTURE_GEN_R);
3500 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3501 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3502 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR)");
3506 case D3DTSS_TCI_CAMERASPACENORMAL:
3508 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3509 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3510 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3511 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3512 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3513 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3515 glMatrixMode(GL_MODELVIEW);
3518 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3519 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3520 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3521 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3524 glEnable(GL_TEXTURE_GEN_S);
3525 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3526 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3527 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3528 glEnable(GL_TEXTURE_GEN_T);
3529 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3530 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3531 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3532 glEnable(GL_TEXTURE_GEN_R);
3533 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3534 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3535 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV)");
3540 case D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3542 if (GL_SUPPORT(NV_TEXGEN_REFLECTION)) {
3543 float s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3544 float t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3545 float r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3546 float q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3547 TRACE("D3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane\n");
3549 glMatrixMode(GL_MODELVIEW);
3552 glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3553 glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3554 glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3555 glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3558 glEnable(GL_TEXTURE_GEN_S);
3559 checkGLcall("glEnable(GL_TEXTURE_GEN_S);");
3560 glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3561 checkGLcall("glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3562 glEnable(GL_TEXTURE_GEN_T);
3563 checkGLcall("glEnable(GL_TEXTURE_GEN_T);");
3564 glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3565 checkGLcall("glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3566 glEnable(GL_TEXTURE_GEN_R);
3567 checkGLcall("glEnable(GL_TEXTURE_GEN_R);");
3568 glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3569 checkGLcall("glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV)");
3574 /* Unhandled types: */
3577 /* ? disable GL_TEXTURE_GEN_n ? */
3578 glDisable(GL_TEXTURE_GEN_S);
3579 glDisable(GL_TEXTURE_GEN_T);
3580 glDisable(GL_TEXTURE_GEN_R);
3581 FIXME("Unhandled D3DTSS_TEXCOORDINDEX %lx\n", Value);
3588 case D3DTSS_TEXTURETRANSFORMFLAGS :
3589 set_texture_matrix((float *)&This->StateBlock->transforms[D3DTS_TEXTURE0 + Stage].u.m[0][0], Value);
3592 case D3DTSS_BUMPENVMAT00 :
3593 case D3DTSS_BUMPENVMAT01 :
3594 TRACE("BUMPENVMAT0%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT00, Stage, Type, Value);
3596 case D3DTSS_BUMPENVMAT10 :
3597 case D3DTSS_BUMPENVMAT11 :
3598 TRACE("BUMPENVMAT1%u Stage=%ld, Type=%d, Value =%ld\n", Type - D3DTSS_BUMPENVMAT10, Stage, Type, Value);
3601 case D3DTSS_BUMPENVLSCALE :
3602 TRACE("BUMPENVLSCALE Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3605 case D3DTSS_BUMPENVLOFFSET :
3606 TRACE("BUMPENVLOFFSET Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3609 case D3DTSS_RESULTARG :
3610 TRACE("RESULTARG Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3614 /* Put back later: FIXME("(%p) : stub, Stage=%ld, Type=%d, Value =%ld\n", This, Stage, Type, Value); */
3615 TRACE("Still a stub, Stage=%ld, Type=%d, Value =%ld\n", Stage, Type, Value);
3622 HRESULT WINAPI IDirect3DDevice8Impl_ValidateDevice(LPDIRECT3DDEVICE8 iface, DWORD* pNumPasses) {
3623 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3624 TRACE("(%p) : stub\n", This); /* FIXME: Needs doing, but called often and is harmless */
3627 HRESULT WINAPI IDirect3DDevice8Impl_GetInfo(LPDIRECT3DDEVICE8 iface, DWORD DevInfoID, void* pDevInfoStruct, DWORD DevInfoStructSize) {
3628 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3629 FIXME("(%p) : stub\n", This);
3632 HRESULT WINAPI IDirect3DDevice8Impl_SetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, CONST PALETTEENTRY* pEntries) {
3633 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3634 FIXME("(%p) : setting p[%u] <= RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3635 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3636 if (PaletteNumber >= MAX_PALETTES) {
3637 return D3DERR_INVALIDCALL;
3639 memcpy(This->palettes[PaletteNumber], pEntries, 256 * sizeof(PALETTEENTRY));
3642 HRESULT WINAPI IDirect3DDevice8Impl_GetPaletteEntries(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber, PALETTEENTRY* pEntries) {
3643 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3644 if (PaletteNumber >= MAX_PALETTES) {
3645 return D3DERR_INVALIDCALL;
3647 memcpy(pEntries, This->palettes[PaletteNumber], 256 * sizeof(PALETTEENTRY));
3648 FIXME("(%p) : returning p[%u] => RGBA(%02x,%02x,%02x,%02x)\n", This, PaletteNumber,
3649 pEntries->peRed, pEntries->peGreen, pEntries->peBlue, pEntries->peFlags);
3652 HRESULT WINAPI IDirect3DDevice8Impl_SetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT PaletteNumber) {
3653 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3654 FIXME("(%p) : Setting to (%u)\n", This, PaletteNumber);
3655 if (PaletteNumber >= MAX_PALETTES) {
3656 return D3DERR_INVALIDCALL;
3658 This->currentPalette = PaletteNumber;
3660 #if defined(GL_EXT_paletted_texture)
3661 if (GL_SUPPORT(EXT_PALETTED_TEXTURE)) {
3665 GL_EXTCALL(glColorTableEXT)(GL_TEXTURE_2D, /* target */
3666 GL_RGBA, /* internal format */
3667 256, /* table size */
3668 GL_RGBA, /* table format */
3669 GL_UNSIGNED_BYTE, /* table type */
3670 This->palettes[PaletteNumber]);
3671 checkGLcall("glColorTableEXT");
3676 /* Delayed palette handling ... waiting for software emulation into preload code */
3681 HRESULT WINAPI IDirect3DDevice8Impl_GetCurrentTexturePalette(LPDIRECT3DDEVICE8 iface, UINT *PaletteNumber) {
3682 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3683 *PaletteNumber = This->currentPalette;
3684 FIXME("(%p) : Returning (%u)\n", This, *PaletteNumber);
3687 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) {
3689 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3690 This->StateBlock->streamIsUP = FALSE;
3692 TRACE("(%p) : Type=(%d,%s), Start=%d, Count=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType), StartVertex, PrimitiveCount);
3693 drawPrimitive(iface, PrimitiveType, PrimitiveCount, StartVertex, -1, 0, NULL, 0);
3697 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitive(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,
3698 UINT minIndex,UINT NumVertices,UINT startIndex,UINT primCount) {
3700 IDirect3DIndexBuffer8 *pIB;
3701 D3DINDEXBUFFER_DESC IdxBufDsc;
3703 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3704 pIB = This->StateBlock->pIndexData;
3705 This->StateBlock->streamIsUP = FALSE;
3707 TRACE("(%p) : Type=(%d,%s), min=%d, CountV=%d, startIdx=%d, countP=%d\n", This,
3708 PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3709 minIndex, NumVertices, startIndex, primCount);
3711 IDirect3DIndexBuffer8Impl_GetDesc(pIB, &IdxBufDsc);
3712 if (IdxBufDsc.Format == D3DFMT_INDEX16) {
3718 drawPrimitive(iface, PrimitiveType, primCount, This->StateBlock->baseVertexIndex, startIndex, idxStride, ((IDirect3DIndexBuffer8Impl *) pIB)->allocatedMemory,
3723 HRESULT WINAPI IDirect3DDevice8Impl_DrawPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT PrimitiveCount,CONST void* pVertexStreamZeroData,UINT VertexStreamZeroStride) {
3724 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3726 TRACE("(%p) : Type=(%d,%s), pCount=%d, pVtxData=%p, Stride=%d\n", This, PrimitiveType, debug_d3dprimitivetype(PrimitiveType),
3727 PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride);
3729 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3731 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3732 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3733 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3734 This->StateBlock->streamIsUP = TRUE;
3735 drawPrimitive(iface, PrimitiveType, PrimitiveCount, 0, 0, 0, NULL, 0);
3736 This->StateBlock->stream_stride[0] = 0;
3737 This->StateBlock->stream_source[0] = NULL;
3739 /*stream zero settings set to null at end */
3742 HRESULT WINAPI IDirect3DDevice8Impl_DrawIndexedPrimitiveUP(LPDIRECT3DDEVICE8 iface, D3DPRIMITIVETYPE PrimitiveType,UINT MinVertexIndex,
3743 UINT NumVertexIndices,UINT PrimitiveCount,CONST void* pIndexData,
3744 D3DFORMAT IndexDataFormat,CONST void* pVertexStreamZeroData,
3745 UINT VertexStreamZeroStride) {
3747 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3748 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),
3749 MinVertexIndex, NumVertexIndices, PrimitiveCount, pIndexData, IndexDataFormat, pVertexStreamZeroData, VertexStreamZeroStride);
3751 if (This->StateBlock->stream_source[0] != NULL) IDirect3DVertexBuffer8Impl_Release(This->StateBlock->stream_source[0]);
3752 if (IndexDataFormat == D3DFMT_INDEX16) {
3758 /* Note in the following, its not this type, but thats the purpose of streamIsUP */
3759 This->StateBlock->stream_source[0] = (IDirect3DVertexBuffer8 *)pVertexStreamZeroData;
3760 This->StateBlock->streamIsUP = TRUE;
3761 This->StateBlock->stream_stride[0] = VertexStreamZeroStride;
3762 drawPrimitive(iface, PrimitiveType, PrimitiveCount, This->StateBlock->baseVertexIndex, 0, idxStride, pIndexData, MinVertexIndex);
3764 /*stream zero settings set to null at end */
3765 This->StateBlock->stream_source[0] = NULL;
3766 This->StateBlock->stream_stride[0] = 0;
3767 IDirect3DDevice8Impl_SetIndices(iface, NULL, 0);
3771 HRESULT WINAPI IDirect3DDevice8Impl_ProcessVertices(LPDIRECT3DDEVICE8 iface, UINT SrcStartIndex,UINT DestIndex,UINT VertexCount,IDirect3DVertexBuffer8* pDestBuffer,DWORD Flags) {
3772 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3773 FIXME("(%p) : stub\n", This); return D3D_OK;
3775 HRESULT WINAPI IDirect3DDevice8Impl_CreateVertexShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pDeclaration, CONST DWORD* pFunction, DWORD* pHandle, DWORD Usage) {
3776 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3777 IDirect3DVertexShaderImpl* object;
3778 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3782 TRACE_(d3d_shader)("(%p) : VertexShader not fully supported yet : Decl=%p, Func=%p, Usage=%lu\n", This, pDeclaration, pFunction, Usage);
3783 if (NULL == pDeclaration || NULL == pHandle) { /* pFunction can be NULL see MSDN */
3784 return D3DERR_INVALIDCALL;
3786 for (i = 1; NULL != VertexShaders[i] && i < sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*); ++i) ;
3787 if (i >= sizeof(VertexShaders) / sizeof(IDirect3DVertexShaderImpl*)) {
3788 return D3DERR_OUTOFVIDEOMEMORY;
3791 /** Create the Vertex Shader */
3792 res = IDirect3DDeviceImpl_CreateVertexShader(This, pFunction, Usage, &object);
3793 /** TODO: check FAILED(res) */
3795 /** Create and Bind the Vertex Shader Declaration */
3796 res = IDirect3DDeviceImpl_CreateVertexShaderDeclaration8(This, pDeclaration, &attached_decl);
3797 /** TODO: check FAILED(res) */
3799 VertexShaders[i] = object;
3800 VertexShaderDeclarations[i] = attached_decl;
3801 *pHandle = VS_HIGHESTFIXEDFXF + i;
3802 TRACE("Finished creating vertex shader %lx\n", *pHandle);
3806 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3807 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3809 This->UpdateStateBlock->VertexShader = Handle;
3810 This->UpdateStateBlock->Changed.vertexShader = TRUE;
3811 This->UpdateStateBlock->Set.vertexShader = TRUE;
3813 if (Handle > VS_HIGHESTFIXEDFXF) { /* only valid with non FVF shaders */
3814 TRACE_(d3d_shader)("(%p) : Created shader, Handle=%lx\n", This, Handle);
3815 This->UpdateStateBlock->vertexShaderDecl = VERTEX_SHADER_DECL(Handle);
3816 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3817 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3818 } else { /* use a fvf, so desactivate the vshader decl */
3819 TRACE("(%p) : FVF Shader, Handle=%lx\n", This, Handle);
3820 This->UpdateStateBlock->vertexShaderDecl = NULL;
3821 This->UpdateStateBlock->Changed.vertexShaderDecl = TRUE;
3822 This->UpdateStateBlock->Set.vertexShaderDecl = TRUE;
3824 /* Handle recording of state blocks */
3825 if (This->isRecordingState) {
3826 TRACE("Recording... not performing anything\n");
3830 * TODO: merge HAL shaders context switching from prototype
3834 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
3835 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3836 TRACE_(d3d_shader)("(%p) : GetVertexShader returning %ld\n", This, This->StateBlock->VertexShader);
3837 *pHandle = This->StateBlock->VertexShader;
3841 HRESULT WINAPI IDirect3DDevice8Impl_DeleteVertexShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
3842 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3843 IDirect3DVertexShaderImpl* object;
3844 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3846 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
3847 return D3DERR_INVALIDCALL;
3851 * Delete Vertex Shader
3853 object = VertexShaders[Handle - VS_HIGHESTFIXEDFXF];
3854 if (NULL == object) {
3855 return D3DERR_INVALIDCALL;
3857 TRACE_(d3d_shader)("(%p) : freing VertexShader %p\n", This, object);
3858 /* TODO: check validity of object */
3859 HeapFree(GetProcessHeap(), 0, (void *)object->function);
3860 if (object->prgId != 0) {
3861 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
3863 HeapFree(GetProcessHeap(), 0, (void *)object->data);
3864 HeapFree(GetProcessHeap(), 0, (void *)object);
3865 VertexShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3868 * Delete Vertex Shader Declaration
3870 attached_decl = VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF];
3871 if (NULL == attached_decl) {
3872 return D3DERR_INVALIDCALL;
3874 TRACE_(d3d_shader)("(%p) : freing VertexShaderDeclaration %p\n", This, attached_decl);
3875 /* TODO: check validity of object */
3876 HeapFree(GetProcessHeap(), 0, (void *)attached_decl->pDeclaration8);
3877 HeapFree(GetProcessHeap(), 0, (void *)attached_decl);
3878 VertexShaderDeclarations[Handle - VS_HIGHESTFIXEDFXF] = NULL;
3883 HRESULT WINAPI IDirect3DDevice8Impl_SetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
3884 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3886 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3887 ERR_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu] invalid\n", This, Register);
3888 return D3DERR_INVALIDCALL;
3890 if (NULL == pConstantData) {
3891 return D3DERR_INVALIDCALL;
3893 if (ConstantCount > 1) {
3894 const FLOAT* f = (const FLOAT*)pConstantData;
3896 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
3897 for (i = 0; i < ConstantCount; ++i) {
3898 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
3902 const FLOAT* f = (const FLOAT*) pConstantData;
3903 TRACE_(d3d_shader)("(%p) : SetVertexShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
3905 This->UpdateStateBlock->Changed.vertexShaderConstant = TRUE;
3906 memcpy(&This->UpdateStateBlock->vertexShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
3909 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
3910 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3912 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
3913 if (Register + ConstantCount > D3D8_VSHADER_MAX_CONSTANTS) {
3914 return D3DERR_INVALIDCALL;
3916 if (NULL == pConstantData) {
3917 return D3DERR_INVALIDCALL;
3919 memcpy(pConstantData, &This->UpdateStateBlock->vertexShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
3922 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderDeclaration(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3923 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
3924 IDirect3DVertexShaderDeclarationImpl* attached_decl;
3926 attached_decl = VERTEX_SHADER_DECL(Handle);
3927 if (NULL == attached_decl) {
3928 return D3DERR_INVALIDCALL;
3930 return IDirect3DVertexShaderDeclarationImpl_GetDeclaration8(attached_decl, pData, (UINT*) pSizeOfData);
3932 HRESULT WINAPI IDirect3DDevice8Impl_GetVertexShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
3933 /*IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;*/
3934 IDirect3DVertexShaderImpl* object;
3936 object = VERTEX_SHADER(Handle);
3937 if (NULL == object) {
3938 return D3DERR_INVALIDCALL;
3940 return IDirect3DVertexShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
3943 HRESULT WINAPI IDirect3DDevice8Impl_SetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8* pIndexData, UINT BaseVertexIndex) {
3944 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3945 IDirect3DIndexBuffer8 *oldIdxs;
3947 TRACE("(%p) : Setting to %p, base %d\n", This, pIndexData, BaseVertexIndex);
3948 oldIdxs = This->StateBlock->pIndexData;
3950 This->UpdateStateBlock->Changed.Indices = TRUE;
3951 This->UpdateStateBlock->Set.Indices = TRUE;
3952 This->UpdateStateBlock->pIndexData = pIndexData;
3953 This->UpdateStateBlock->baseVertexIndex = BaseVertexIndex;
3955 /* Handle recording of state blocks */
3956 if (This->isRecordingState) {
3957 TRACE("Recording... not performing anything\n");
3961 if (pIndexData) IDirect3DIndexBuffer8Impl_AddRefInt(This->StateBlock->pIndexData);
3962 if (oldIdxs) IDirect3DIndexBuffer8Impl_ReleaseInt(oldIdxs);
3965 HRESULT WINAPI IDirect3DDevice8Impl_GetIndices(LPDIRECT3DDEVICE8 iface, IDirect3DIndexBuffer8** ppIndexData,UINT* pBaseVertexIndex) {
3966 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3967 FIXME("(%p) : stub\n", This);
3969 *ppIndexData = This->StateBlock->pIndexData;
3970 /* up ref count on ppindexdata */
3971 if (*ppIndexData) IDirect3DIndexBuffer8Impl_AddRef(*ppIndexData);
3972 *pBaseVertexIndex = This->StateBlock->baseVertexIndex;
3976 HRESULT WINAPI IDirect3DDevice8Impl_CreatePixelShader(LPDIRECT3DDEVICE8 iface, CONST DWORD* pFunction, DWORD* pHandle) {
3977 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
3978 IDirect3DPixelShaderImpl* object;
3982 TRACE_(d3d_shader)("(%p) : PixelShader not fully supported yet : Func=%p\n", This, pFunction);
3983 if (NULL == pFunction || NULL == pHandle) {
3984 return D3DERR_INVALIDCALL;
3986 for (i = 1; NULL != PixelShaders[i] && i < sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*); ++i) ;
3987 if (i >= sizeof(PixelShaders) / sizeof(IDirect3DPixelShaderImpl*)) {
3988 return D3DERR_OUTOFVIDEOMEMORY;
3991 /** Create the Pixel Shader */
3992 res = IDirect3DDeviceImpl_CreatePixelShader(This, pFunction, &object);
3993 if (SUCCEEDED(res)) {
3994 PixelShaders[i] = object;
3995 *pHandle = VS_HIGHESTFIXEDFXF + i;
3998 *pHandle = 0xFFFFFFFF;
4002 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4003 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4005 This->UpdateStateBlock->PixelShader = Handle;
4006 This->UpdateStateBlock->Changed.pixelShader = TRUE;
4007 This->UpdateStateBlock->Set.pixelShader = TRUE;
4009 /* Handle recording of state blocks */
4010 if (This->isRecordingState) {
4011 TRACE_(d3d_shader)("Recording... not performing anything\n");
4016 TRACE_(d3d_shader)("(%p) : Set pixel shader with handle %lx\n", This, Handle);
4018 TRACE_(d3d_shader)("(%p) : Remove pixel shader\n", This);
4024 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShader(LPDIRECT3DDEVICE8 iface, DWORD* pHandle) {
4025 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4026 TRACE_(d3d_shader)("(%p) : GetPixelShader returning %ld\n", This, This->StateBlock->PixelShader);
4027 *pHandle = This->StateBlock->PixelShader;
4031 HRESULT WINAPI IDirect3DDevice8Impl_DeletePixelShader(LPDIRECT3DDEVICE8 iface, DWORD Handle) {
4032 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4033 IDirect3DPixelShaderImpl* object;
4035 if (Handle <= VS_HIGHESTFIXEDFXF) { /* only delete user defined shaders */
4036 return D3DERR_INVALIDCALL;
4038 object = PixelShaders[Handle - VS_HIGHESTFIXEDFXF];
4039 if (NULL == object) {
4040 return D3DERR_INVALIDCALL;
4042 TRACE_(d3d_shader)("(%p) : freeing PixelShader %p\n", This, object);
4043 /* TODO: check validity of object before free */
4044 HeapFree(GetProcessHeap(), 0, (void *)object->function);
4045 if (object->prgId != 0) {
4046 GL_EXTCALL(glDeleteProgramsARB( 1, &object->prgId ));
4048 HeapFree(GetProcessHeap(), 0, (void *)object->data);
4049 HeapFree(GetProcessHeap(), 0, (void *)object);
4050 PixelShaders[Handle - VS_HIGHESTFIXEDFXF] = NULL;
4055 HRESULT WINAPI IDirect3DDevice8Impl_SetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, CONST void* pConstantData, DWORD ConstantCount) {
4056 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4058 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4059 ERR_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu] invalid\n", This, Register);
4060 return D3DERR_INVALIDCALL;
4062 if (NULL == pConstantData) {
4063 return D3DERR_INVALIDCALL;
4065 if (ConstantCount > 1) {
4066 const FLOAT* f = (const FLOAT*)pConstantData;
4068 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant C[%lu..%lu]=\n", This, Register, Register + ConstantCount - 1);
4069 for (i = 0; i < ConstantCount; ++i) {
4070 TRACE_(d3d_shader)("{%f, %f, %f, %f}\n", f[0], f[1], f[2], f[3]);
4074 const FLOAT* f = (const FLOAT*) pConstantData;
4075 TRACE_(d3d_shader)("(%p) : SetPixelShaderConstant, C[%lu]={%f, %f, %f, %f}\n", This, Register, f[0], f[1], f[2], f[3]);
4077 This->UpdateStateBlock->Changed.pixelShaderConstant = TRUE;
4078 memcpy(&This->UpdateStateBlock->pixelShaderConstant[Register], pConstantData, ConstantCount * 4 * sizeof(FLOAT));
4081 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderConstant(LPDIRECT3DDEVICE8 iface, DWORD Register, void* pConstantData, DWORD ConstantCount) {
4082 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4084 TRACE_(d3d_shader)("(%p) : C[%lu] count=%ld\n", This, Register, ConstantCount);
4085 if (Register + ConstantCount > D3D8_PSHADER_MAX_CONSTANTS) {
4086 return D3DERR_INVALIDCALL;
4088 if (NULL == pConstantData) {
4089 return D3DERR_INVALIDCALL;
4091 memcpy(pConstantData, &This->UpdateStateBlock->pixelShaderConstant[Register], ConstantCount * 4 * sizeof(FLOAT));
4094 HRESULT WINAPI IDirect3DDevice8Impl_GetPixelShaderFunction(LPDIRECT3DDEVICE8 iface, DWORD Handle, void* pData, DWORD* pSizeOfData) {
4095 IDirect3DPixelShaderImpl* object;
4097 object = PIXEL_SHADER(Handle);
4098 if (NULL == object) {
4099 return D3DERR_INVALIDCALL;
4101 return IDirect3DPixelShaderImpl_GetFunction(object, pData, (UINT*) pSizeOfData);
4103 HRESULT WINAPI IDirect3DDevice8Impl_DrawRectPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DRECTPATCH_INFO* pRectPatchInfo) {
4104 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4105 FIXME("(%p) : stub\n", This); return D3D_OK;
4107 HRESULT WINAPI IDirect3DDevice8Impl_DrawTriPatch(LPDIRECT3DDEVICE8 iface, UINT Handle,CONST float* pNumSegs,CONST D3DTRIPATCH_INFO* pTriPatchInfo) {
4108 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4109 FIXME("(%p) : stub\n", This); return D3D_OK;
4111 HRESULT WINAPI IDirect3DDevice8Impl_DeletePatch(LPDIRECT3DDEVICE8 iface, UINT Handle) {
4112 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4113 FIXME("(%p) : stub\n", This); return D3D_OK;
4116 HRESULT WINAPI IDirect3DDevice8Impl_SetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8* pStreamData,UINT Stride) {
4117 IDirect3DVertexBuffer8 *oldSrc;
4118 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4120 oldSrc = This->StateBlock->stream_source[StreamNumber];
4121 TRACE("(%p) : StreamNo: %d, OldStream (%p), NewStream (%p), NewStride %d\n", This, StreamNumber, oldSrc, pStreamData, Stride);
4123 This->UpdateStateBlock->Changed.stream_source[StreamNumber] = TRUE;
4124 This->UpdateStateBlock->Set.stream_source[StreamNumber] = TRUE;
4125 This->UpdateStateBlock->stream_stride[StreamNumber] = Stride;
4126 This->UpdateStateBlock->stream_source[StreamNumber] = pStreamData;
4128 /* Handle recording of state blocks */
4129 if (This->isRecordingState) {
4130 TRACE("Recording... not performing anything\n");
4134 if (pStreamData != NULL) IDirect3DVertexBuffer8Impl_AddRefInt(pStreamData);
4135 if (oldSrc != NULL) IDirect3DVertexBuffer8Impl_ReleaseInt(oldSrc);
4138 HRESULT WINAPI IDirect3DDevice8Impl_GetStreamSource(LPDIRECT3DDEVICE8 iface, UINT StreamNumber,IDirect3DVertexBuffer8** pStream,UINT* pStride) {
4139 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4140 TRACE("(%p) : StreamNo: %d, Stream (%p), Stride %d\n", This, StreamNumber, This->StateBlock->stream_source[StreamNumber], This->StateBlock->stream_stride[StreamNumber]);
4141 *pStream = This->StateBlock->stream_source[StreamNumber];
4142 *pStride = This->StateBlock->stream_stride[StreamNumber];
4143 if (*pStream != NULL) IDirect3DVertexBuffer8Impl_AddRef((LPDIRECT3DVERTEXBUFFER8) *pStream);
4148 const IDirect3DDevice8Vtbl Direct3DDevice8_Vtbl =
4150 IDirect3DDevice8Impl_QueryInterface,
4151 IDirect3DDevice8Impl_AddRef,
4152 IDirect3DDevice8Impl_Release,
4153 IDirect3DDevice8Impl_TestCooperativeLevel,
4154 IDirect3DDevice8Impl_GetAvailableTextureMem,
4155 IDirect3DDevice8Impl_ResourceManagerDiscardBytes,
4156 IDirect3DDevice8Impl_GetDirect3D,
4157 IDirect3DDevice8Impl_GetDeviceCaps,
4158 IDirect3DDevice8Impl_GetDisplayMode,
4159 IDirect3DDevice8Impl_GetCreationParameters,
4160 IDirect3DDevice8Impl_SetCursorProperties,
4161 IDirect3DDevice8Impl_SetCursorPosition,
4162 IDirect3DDevice8Impl_ShowCursor,
4163 IDirect3DDevice8Impl_CreateAdditionalSwapChain,
4164 IDirect3DDevice8Impl_Reset,
4165 IDirect3DDevice8Impl_Present,
4166 IDirect3DDevice8Impl_GetBackBuffer,
4167 IDirect3DDevice8Impl_GetRasterStatus,
4168 IDirect3DDevice8Impl_SetGammaRamp,
4169 IDirect3DDevice8Impl_GetGammaRamp,
4170 IDirect3DDevice8Impl_CreateTexture,
4171 IDirect3DDevice8Impl_CreateVolumeTexture,
4172 IDirect3DDevice8Impl_CreateCubeTexture,
4173 IDirect3DDevice8Impl_CreateVertexBuffer,
4174 IDirect3DDevice8Impl_CreateIndexBuffer,
4175 IDirect3DDevice8Impl_CreateRenderTarget,
4176 IDirect3DDevice8Impl_CreateDepthStencilSurface,
4177 IDirect3DDevice8Impl_CreateImageSurface,
4178 IDirect3DDevice8Impl_CopyRects,
4179 IDirect3DDevice8Impl_UpdateTexture,
4180 IDirect3DDevice8Impl_GetFrontBuffer,
4181 IDirect3DDevice8Impl_SetRenderTarget,
4182 IDirect3DDevice8Impl_GetRenderTarget,
4183 IDirect3DDevice8Impl_GetDepthStencilSurface,
4184 IDirect3DDevice8Impl_BeginScene,
4185 IDirect3DDevice8Impl_EndScene,
4186 IDirect3DDevice8Impl_Clear,
4187 IDirect3DDevice8Impl_SetTransform,
4188 IDirect3DDevice8Impl_GetTransform,
4189 IDirect3DDevice8Impl_MultiplyTransform,
4190 IDirect3DDevice8Impl_SetViewport,
4191 IDirect3DDevice8Impl_GetViewport,
4192 IDirect3DDevice8Impl_SetMaterial,
4193 IDirect3DDevice8Impl_GetMaterial,
4194 IDirect3DDevice8Impl_SetLight,
4195 IDirect3DDevice8Impl_GetLight,
4196 IDirect3DDevice8Impl_LightEnable,
4197 IDirect3DDevice8Impl_GetLightEnable,
4198 IDirect3DDevice8Impl_SetClipPlane,
4199 IDirect3DDevice8Impl_GetClipPlane,
4200 IDirect3DDevice8Impl_SetRenderState,
4201 IDirect3DDevice8Impl_GetRenderState,
4202 IDirect3DDevice8Impl_BeginStateBlock,
4203 IDirect3DDevice8Impl_EndStateBlock,
4204 IDirect3DDevice8Impl_ApplyStateBlock,
4205 IDirect3DDevice8Impl_CaptureStateBlock,
4206 IDirect3DDevice8Impl_DeleteStateBlock,
4207 IDirect3DDevice8Impl_CreateStateBlock,
4208 IDirect3DDevice8Impl_SetClipStatus,
4209 IDirect3DDevice8Impl_GetClipStatus,
4210 IDirect3DDevice8Impl_GetTexture,
4211 IDirect3DDevice8Impl_SetTexture,
4212 IDirect3DDevice8Impl_GetTextureStageState,
4213 IDirect3DDevice8Impl_SetTextureStageState,
4214 IDirect3DDevice8Impl_ValidateDevice,
4215 IDirect3DDevice8Impl_GetInfo,
4216 IDirect3DDevice8Impl_SetPaletteEntries,
4217 IDirect3DDevice8Impl_GetPaletteEntries,
4218 IDirect3DDevice8Impl_SetCurrentTexturePalette,
4219 IDirect3DDevice8Impl_GetCurrentTexturePalette,
4220 IDirect3DDevice8Impl_DrawPrimitive,
4221 IDirect3DDevice8Impl_DrawIndexedPrimitive,
4222 IDirect3DDevice8Impl_DrawPrimitiveUP,
4223 IDirect3DDevice8Impl_DrawIndexedPrimitiveUP,
4224 IDirect3DDevice8Impl_ProcessVertices,
4225 IDirect3DDevice8Impl_CreateVertexShader,
4226 IDirect3DDevice8Impl_SetVertexShader,
4227 IDirect3DDevice8Impl_GetVertexShader,
4228 IDirect3DDevice8Impl_DeleteVertexShader,
4229 IDirect3DDevice8Impl_SetVertexShaderConstant,
4230 IDirect3DDevice8Impl_GetVertexShaderConstant,
4231 IDirect3DDevice8Impl_GetVertexShaderDeclaration,
4232 IDirect3DDevice8Impl_GetVertexShaderFunction,
4233 IDirect3DDevice8Impl_SetStreamSource,
4234 IDirect3DDevice8Impl_GetStreamSource,
4235 IDirect3DDevice8Impl_SetIndices,
4236 IDirect3DDevice8Impl_GetIndices,
4237 IDirect3DDevice8Impl_CreatePixelShader,
4238 IDirect3DDevice8Impl_SetPixelShader,
4239 IDirect3DDevice8Impl_GetPixelShader,
4240 IDirect3DDevice8Impl_DeletePixelShader,
4241 IDirect3DDevice8Impl_SetPixelShaderConstant,
4242 IDirect3DDevice8Impl_GetPixelShaderConstant,
4243 IDirect3DDevice8Impl_GetPixelShaderFunction,
4244 IDirect3DDevice8Impl_DrawRectPatch,
4245 IDirect3DDevice8Impl_DrawTriPatch,
4246 IDirect3DDevice8Impl_DeletePatch
4249 HRESULT WINAPI IDirect3DDevice8Impl_CleanRender(LPDIRECT3DDEVICE8 iface)
4251 #if defined(GL_VERSION_1_3) /* @see comments on ActiveRender */
4252 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4257 if (This->glCtx != This->render_ctx) {
4258 glXDestroyContext(This->display, This->render_ctx);
4259 This->render_ctx = This->glCtx;
4262 if (This->win != This->drawable) {
4263 glXDestroyPbuffer(This->display, This->drawable);
4264 This->drawable = This->win;
4273 HRESULT WINAPI IDirect3DDevice8Impl_ActiveRender(LPDIRECT3DDEVICE8 iface,
4274 IDirect3DSurface8* RenderSurface,
4275 IDirect3DSurface8* StencilSurface) {
4277 HRESULT ret = D3DERR_INVALIDCALL;
4279 * Currently only active for GLX >= 1.3
4280 * for others versions we'll have to use GLXPixmaps
4282 * normally we must test GLX_VERSION_1_3 but nvidia headers are not correct
4283 * as they implements GLX 1.3 but only define GLX_VERSION_1_2
4284 * so only check OpenGL version
4286 #if defined(GL_VERSION_1_3)
4287 GLXFBConfig* cfgs = NULL;
4291 D3DFORMAT BackBufferFormat = D3D8_SURFACE(((IDirect3DSurface8Impl*) RenderSurface))->resource.format;
4292 D3DFORMAT StencilBufferFormat = (NULL != StencilSurface) ? D3D8_SURFACE(((IDirect3DSurface8Impl*) StencilSurface))->resource.format : 0;
4293 UINT Width = D3D8_SURFACE(((IDirect3DSurface8Impl*) RenderSurface))->currentDesc.Width;
4294 UINT Height = D3D8_SURFACE(((IDirect3DSurface8Impl*) RenderSurface))->currentDesc.Height;
4295 IDirect3DSurface8Impl* tmp;
4297 IDirect3DDevice8Impl *This = (IDirect3DDevice8Impl *)iface;
4299 #define PUSH1(att) attribs[nAttribs++] = (att);
4300 #define PUSH2(att,value) attribs[nAttribs++] = (att); attribs[nAttribs++] = (value);
4302 PUSH2(GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT);
4303 PUSH2(GLX_X_RENDERABLE, TRUE);
4304 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4306 switch (BackBufferFormat) {
4309 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
4310 PUSH2(GLX_BUFFER_SIZE, 8);
4311 PUSH2(GLX_DOUBLEBUFFER, TRUE);
4315 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
4316 PUSH2(GLX_RED_SIZE, 3);
4317 PUSH2(GLX_GREEN_SIZE, 3);
4318 PUSH2(GLX_BLUE_SIZE, 2);
4321 case D3DFMT_A1R5G5B5:
4322 PUSH2(GLX_ALPHA_SIZE, 1);
4323 case D3DFMT_X1R5G5B5:
4324 PUSH2(GLX_RED_SIZE, 5);
4325 PUSH2(GLX_GREEN_SIZE, 5);
4326 PUSH2(GLX_BLUE_SIZE, 5);
4330 PUSH2(GLX_RED_SIZE, 5);
4331 PUSH2(GLX_GREEN_SIZE, 6);
4332 PUSH2(GLX_BLUE_SIZE, 5);
4335 case D3DFMT_A4R4G4B4:
4336 PUSH2(GLX_ALPHA_SIZE, 4);
4337 case D3DFMT_X4R4G4B4:
4338 PUSH2(GLX_RED_SIZE, 4);
4339 PUSH2(GLX_GREEN_SIZE, 4);
4340 PUSH2(GLX_BLUE_SIZE, 4);
4343 case D3DFMT_A8R8G8B8:
4344 PUSH2(GLX_ALPHA_SIZE, 8);
4346 case D3DFMT_X8R8G8B8:
4347 PUSH2(GLX_RED_SIZE, 8);
4348 PUSH2(GLX_GREEN_SIZE, 8);
4349 PUSH2(GLX_BLUE_SIZE, 8);
4356 switch (StencilBufferFormat) {
4357 case D3DFMT_D16_LOCKABLE:
4359 PUSH2(GLX_DEPTH_SIZE, 16);
4363 PUSH2(GLX_DEPTH_SIZE, 15);
4367 PUSH2(GLX_DEPTH_SIZE, 24);
4370 case D3DFMT_D24X4S4:
4371 PUSH2(GLX_DEPTH_SIZE, 24);
4372 PUSH2(GLX_STENCIL_SIZE, 4);
4376 PUSH2(GLX_DEPTH_SIZE, 24);
4377 PUSH2(GLX_STENCIL_SIZE, 8);
4381 PUSH2(GLX_DEPTH_SIZE, 24);
4392 cfgs = glXChooseFBConfig(This->display, DefaultScreen(This->display), attribs, &nCfgs);
4396 for (i = 0; i < nCfgs; ++i) {
4397 TRACE("for (%u,%s)/(%u,%s) found config[%d]@%p\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat), i, cfgs[i]);
4401 if (NULL != This->renderTarget) {
4402 /*GLenum prev_read; */
4404 vcheckGLcall("glFlush");
4407 /** very very useful debug code */
4408 glXSwapBuffers(This->display, This->drawable);
4409 printf("Hit Enter to get next frame ...\n");
4414 glGetIntegerv(GL_READ_BUFFER, &prev_read);
4415 vcheckGLcall("glIntegerv");
4416 glReadBuffer(GL_BACK);
4417 vcheckGLcall("glReadBuffer");
4420 long pitch = This->renderTarget->myDesc.Width * This->renderTarget->bytesPerPixel;
4422 if (This->renderTarget->myDesc.Format == D3DFMT_DXT1) /* DXT1 is half byte per pixel */
4425 for (j = 0; j < This->renderTarget->myDesc.Height; ++j) {
4427 This->renderTarget->myDesc.Height - j - 1,
4428 This->renderTarget->myDesc.Width,
4430 D3DFmt2GLFmt(This, This->renderTarget->myDesc.Format),
4431 D3DFmt2GLType(This, This->renderTarget->myDesc.Format),
4432 This->renderTarget->allocatedMemory + j * pitch);
4433 vcheckGLcall("glReadPixels");
4436 glReadBuffer(prev_read);
4437 vcheckGLcall("glReadBuffer");
4441 if (BackBufferFormat != D3D8_SURFACE(This->renderTarget)->resource.format &&
4442 StencilBufferFormat != D3D8_SURFACE(This->stencilBufferTarget)->resource.format) {
4444 PUSH2(GLX_PBUFFER_WIDTH, Width);
4445 PUSH2(GLX_PBUFFER_HEIGHT, Height);
4447 This->drawable = glXCreatePbuffer(This->display, cfgs[0], attribs);
4449 This->render_ctx = glXCreateNewContext(This->display, cfgs[0], GLX_RGBA_TYPE, This->glCtx, TRUE);
4450 if (NULL == This->render_ctx) {
4451 ERR("cannot create glxContext\n");
4455 glXSwapBuffers(This->display, This->drawable);
4456 if (glXMakeContextCurrent(This->display, This->drawable, This->drawable, This->render_ctx) == False) {
4457 TRACE("Error in setting current context: context %p drawable %ld (default %ld)!\n", This->glCtx, This->drawable, This->win);
4459 checkGLcall("glXMakeContextCurrent");
4462 tmp = This->renderTarget;
4463 This->renderTarget = (IDirect3DSurface8Impl*) RenderSurface;
4464 IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->renderTarget);
4465 IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4467 tmp = This->stencilBufferTarget;
4468 This->stencilBufferTarget = (IDirect3DSurface8Impl*) StencilSurface;
4469 if (NULL != This->stencilBufferTarget) IDirect3DSurface8Impl_AddRef((LPDIRECT3DSURFACE8) This->stencilBufferTarget);
4470 if (NULL != tmp) IDirect3DSurface8Impl_Release((LPDIRECT3DSURFACE8) tmp);
4474 /* The surface must be rendered upside down to cancel the flip produce by glCopyTexImage */
4475 This->renderUpsideDown = (This->renderTarget != This->frontBuffer) && (This->renderTarget != This->backBuffer);
4476 /* Force updating the cull mode */
4477 IDirect3DDevice8_GetRenderState(iface, D3DRS_CULLMODE, &value);
4478 IDirect3DDevice8_SetRenderState(iface, D3DRS_CULLMODE, value);
4479 /* Force updating projection matrix */
4480 This->last_was_rhw = FALSE;
4481 This->proj_valid = FALSE;
4487 ERR("cannot get valides GLXFBConfig for (%u,%s)/(%u,%s)\n", BackBufferFormat, debug_d3dformat(BackBufferFormat), StencilBufferFormat, debug_d3dformat(StencilBufferFormat));
4500 /* Internal function called back during the CreateDevice to create a render target */
4501 HRESULT WINAPI D3D8CB_CreateSurface(IUnknown *device, UINT Width, UINT Height,
4502 WINED3DFORMAT Format, DWORD Usage, D3DPOOL Pool, UINT Level,
4503 IWineD3DSurface **ppSurface, HANDLE *pSharedHandle) {
4505 HRESULT res = D3D_OK;
4506 IDirect3DSurface8Impl *d3dSurface = NULL;
4507 BOOL Lockable = TRUE;
4509 if((D3DPOOL_DEFAULT == Pool && D3DUSAGE_DYNAMIC != Usage))
4513 res = IDirect3DDevice8Impl_CreateSurface((IDirect3DDevice8 *)device, Width, Height, (D3DFORMAT)Format, Lockable, FALSE/*Discard*/, Level, (IDirect3DSurface8 **)&d3dSurface, D3DRTYPE_SURFACE, Usage, Pool, D3DMULTISAMPLE_NONE, 0 /* MultisampleQuality */);
4515 if (res == D3D_OK) {
4516 *ppSurface = d3dSurface->wineD3DSurface;
4518 FIXME("(%p) IDirect3DDevice8_CreateSurface failed\n", device);