2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
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
34 #include "wine/debug.h"
36 #include "mesa_private.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
40 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
42 /* x11drv GDI escapes */
43 #define X11DRV_ESCAPE 6789
44 enum x11drv_escape_codes
46 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
47 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
48 X11DRV_GET_FONT, /* get current X font for a DC */
51 /* They are non-static as they are used by Direct3D in the creation function */
52 const GUID IID_D3DDEVICE_OpenGL = {
56 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
59 #ifndef HAVE_GLEXT_PROTOTYPES
60 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
61 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
62 GLsizei width, GLenum format, GLenum type,
66 const float id_mat[16] = {
73 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
74 D3DPRIMITIVETYPE d3dptPrimitiveType,
75 DWORD d3dvtVertexType,
76 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
82 /* retrieve the X display to use on a given DC */
83 inline static Display *get_display( HDC hdc )
86 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
88 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
89 sizeof(display), (LPSTR)&display )) display = NULL;
95 /* retrieve the X drawable to use on a given DC */
96 inline static Drawable get_drawable( HDC hdc )
99 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
101 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
102 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
108 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
110 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
111 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
113 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
115 if (gl_d3d_dev->state == SURFACE_MEMORY_DIRTY) {
116 d3d_dev->flush_to_framebuffer(d3d_dev, NULL, gl_d3d_dev->lock_surf);
118 gl_d3d_dev->state = SURFACE_GL;
119 gl_d3d_dev->front_state = SURFACE_GL;
120 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
127 /*******************************************************************************
128 * OpenGL static functions
130 static void set_context(IDirect3DDeviceImpl* This)
132 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
135 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
136 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
137 ERR("Error in setting current context (context %p drawable %ld)!\n",
138 glThis->gl_context, glThis->drawable);
143 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
145 pc->dwSize = sizeof(*pc);
146 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
147 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
148 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
149 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
150 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
151 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
152 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
153 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
154 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
155 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
156 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
157 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
158 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
159 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
160 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
161 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
162 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
163 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
164 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
165 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
166 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
167 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
168 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
169 pc->dwStippleWidth = 32;
170 pc->dwStippleHeight = 32;
173 static void fill_opengl_caps(D3DDEVICEDESC *d1)
175 /* GLint maxlight; */
177 d1->dwSize = sizeof(*d1);
178 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
179 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
180 d1->dcmColorModel = D3DCOLOR_RGB;
181 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
182 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
183 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
184 /* D3D 7 capabilities */
185 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
186 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
187 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
188 d1->bClipping = TRUE;
189 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
190 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
191 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
192 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
193 fill_opengl_primcaps(&(d1->dpcLineCaps));
194 fill_opengl_primcaps(&(d1->dpcTriCaps));
195 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
196 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
197 d1->dwMaxBufferSize = 0;
198 d1->dwMaxVertexCount = 65536;
199 d1->dwMinTextureWidth = 1;
200 d1->dwMinTextureHeight = 1;
201 d1->dwMaxTextureWidth = 1024;
202 d1->dwMaxTextureHeight = 1024;
203 d1->dwMinStippleWidth = 1;
204 d1->dwMinStippleHeight = 1;
205 d1->dwMaxStippleWidth = 32;
206 d1->dwMaxStippleHeight = 32;
207 d1->dwMaxTextureRepeat = 16;
208 d1->dwMaxTextureAspectRatio = 1024;
209 d1->dwMaxAnisotropy = 0;
210 d1->dvGuardBandLeft = 0.0;
211 d1->dvGuardBandRight = 0.0;
212 d1->dvGuardBandTop = 0.0;
213 d1->dvGuardBandBottom = 0.0;
214 d1->dvExtentsAdjust = 0.0;
215 d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
216 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
217 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
218 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
219 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
220 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
223 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
227 /* Copy first D3D1/2/3 capabilities */
228 fill_opengl_caps(&d1);
230 /* And fill the D3D7 one with it */
231 d->dwDevCaps = d1.dwDevCaps;
232 d->dpcLineCaps = d1.dpcLineCaps;
233 d->dpcTriCaps = d1.dpcTriCaps;
234 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
235 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
236 d->dwMinTextureWidth = d1.dwMinTextureWidth;
237 d->dwMinTextureHeight = d1.dwMinTextureHeight;
238 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
239 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
240 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
241 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
242 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
243 d->dvGuardBandLeft = d1.dvGuardBandLeft;
244 d->dvGuardBandTop = d1.dvGuardBandTop;
245 d->dvGuardBandRight = d1.dvGuardBandRight;
246 d->dvGuardBandBottom = d1.dvGuardBandBottom;
247 d->dvExtentsAdjust = d1.dvExtentsAdjust;
248 d->dwStencilCaps = d1.dwStencilCaps;
249 d->dwFVFCaps = d1.dwFVFCaps;
250 d->dwTextureOpCaps = d1.dwTextureOpCaps;
251 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
252 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
253 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
254 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
255 d->deviceGUID = IID_IDirect3DTnLHalDevice;
256 d->wMaxUserClipPlanes = 1;
257 d->wMaxVertexBlendMatrices = 0;
258 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
259 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
266 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
268 D3DDEVICEDESC dref, d1, d2;
271 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
272 Let's put the string in a sufficiently sized array in writable memory. */
273 char device_name[50];
274 strcpy(device_name,"direct3d");
276 fill_opengl_caps(&dref);
279 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
280 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
283 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
284 if (ret_value != D3DENUMRET_OK)
288 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
291 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
292 if (ret_value != D3DENUMRET_OK)
295 return D3DENUMRET_OK;
298 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
300 D3DDEVICEDESC7 ddesc;
302 fill_opengl_caps_7(&ddesc);
304 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
306 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
310 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
312 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
313 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
315 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
316 if (!--(This->ref)) {
318 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
320 /* Release texture associated with the device */
321 for (i = 0; i < MAX_TEXTURES; i++) {
322 if (This->current_texture[i] != NULL)
323 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
324 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
327 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
328 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
329 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
330 surf->aux_ctx = NULL;
331 surf->aux_data = NULL;
332 surf->aux_flip = NULL;
336 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
337 IDirectDrawSurfaceImpl *surf2;
338 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
339 for (; surf2 != NULL; surf2 = surf2->next_attached) {
340 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
341 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
342 /* Override the Lock / Unlock function for all these surfaces */
343 surf2->lock_update = surf2->lock_update_prev;
344 surf2->unlock_update = surf2->unlock_update_prev;
345 /* And install also the blt / bltfast overrides */
346 surf2->aux_blt = NULL;
347 surf2->aux_bltfast = NULL;
349 surf2->d3ddevice = NULL;
353 /* And warn the D3D object that this device is no longer active... */
354 This->d3d->d3d_removed_device(This->d3d, This);
356 HeapFree(GetProcessHeap(), 0, This->world_mat);
357 HeapFree(GetProcessHeap(), 0, This->view_mat);
358 HeapFree(GetProcessHeap(), 0, This->proj_mat);
360 if (glThis->surface_ptr)
361 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
363 DeleteCriticalSection(&(This->crit));
366 if (glThis->unlock_tex)
367 glDeleteTextures(1, &(glThis->unlock_tex));
368 glXDestroyContext(glThis->display, glThis->gl_context);
370 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
372 HeapFree(GetProcessHeap(), 0, This);
379 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
380 LPD3DDEVICEDESC lpD3DHWDevDesc,
381 LPD3DDEVICEDESC lpD3DHELDevDesc)
383 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
387 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
389 fill_opengl_caps(&desc);
390 dwSize = lpD3DHWDevDesc->dwSize;
391 memset(lpD3DHWDevDesc, 0, dwSize);
392 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
394 dwSize = lpD3DHELDevDesc->dwSize;
395 memset(lpD3DHELDevDesc, 0, dwSize);
396 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
398 TRACE(" returning caps : (no dump function yet)\n");
403 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
404 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
408 LPDDPIXELFORMAT pformat;
410 /* Do the texture enumeration */
411 sdesc.dwSize = sizeof(DDSURFACEDESC);
412 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
413 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
414 pformat = &(sdesc.ddpfPixelFormat);
415 pformat->dwSize = sizeof(DDPIXELFORMAT);
416 pformat->dwFourCC = 0;
418 TRACE("Enumerating GL_RGBA unpacked (32)\n");
419 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
420 pformat->u1.dwRGBBitCount = 32;
421 pformat->u2.dwRBitMask = 0x00FF0000;
422 pformat->u3.dwGBitMask = 0x0000FF00;
423 pformat->u4.dwBBitMask = 0x000000FF;
424 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
425 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
426 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
428 TRACE("Enumerating GL_RGB unpacked (32)\n");
429 pformat->dwFlags = DDPF_RGB;
430 pformat->u1.dwRGBBitCount = 32;
431 pformat->u2.dwRBitMask = 0x00FF0000;
432 pformat->u3.dwGBitMask = 0x0000FF00;
433 pformat->u4.dwBBitMask = 0x000000FF;
434 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
435 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
436 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
438 TRACE("Enumerating GL_RGB unpacked (24)\n");
439 pformat->dwFlags = DDPF_RGB;
440 pformat->u1.dwRGBBitCount = 24;
441 pformat->u2.dwRBitMask = 0x00FF0000;
442 pformat->u3.dwGBitMask = 0x0000FF00;
443 pformat->u4.dwBBitMask = 0x000000FF;
444 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
445 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
446 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
448 /* Note : even if this is an 'emulated' texture format, it needs to be first
449 as some dumb applications seem to rely on that. */
450 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
451 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
452 pformat->u1.dwRGBBitCount = 16;
453 pformat->u2.dwRBitMask = 0x00007C00;
454 pformat->u3.dwGBitMask = 0x000003E0;
455 pformat->u4.dwBBitMask = 0x0000001F;
456 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
457 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
458 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
460 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
461 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
462 pformat->u1.dwRGBBitCount = 16;
463 pformat->u2.dwRBitMask = 0x00000F00;
464 pformat->u3.dwGBitMask = 0x000000F0;
465 pformat->u4.dwBBitMask = 0x0000000F;
466 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
467 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
468 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
470 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
471 pformat->dwFlags = DDPF_RGB;
472 pformat->u1.dwRGBBitCount = 16;
473 pformat->u2.dwRBitMask = 0x0000F800;
474 pformat->u3.dwGBitMask = 0x000007E0;
475 pformat->u4.dwBBitMask = 0x0000001F;
476 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
477 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
478 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
480 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
481 pformat->dwFlags = DDPF_RGB;
482 pformat->u1.dwRGBBitCount = 16;
483 pformat->u2.dwRBitMask = 0x00007C00;
484 pformat->u3.dwGBitMask = 0x000003E0;
485 pformat->u4.dwBBitMask = 0x0000001F;
486 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
487 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
488 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
491 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
492 find enumerated, others the last one. And both want to have the ARGB one.
494 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
496 /* See argument about the RGBA format for 'packed' texture formats */
497 TRACE("Enumerating GL_RGBA unpacked (32)\n");
498 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
499 pformat->u1.dwRGBBitCount = 32;
500 pformat->u2.dwRBitMask = 0xFF000000;
501 pformat->u3.dwGBitMask = 0x00FF0000;
502 pformat->u4.dwBBitMask = 0x0000FF00;
503 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
504 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
505 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
507 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
508 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
509 pformat->u1.dwRGBBitCount = 16;
510 pformat->u2.dwRBitMask = 0x0000F000;
511 pformat->u3.dwGBitMask = 0x00000F00;
512 pformat->u4.dwBBitMask = 0x000000F0;
513 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
514 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
515 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
517 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
518 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
519 pformat->u1.dwRGBBitCount = 16;
520 pformat->u2.dwRBitMask = 0x0000F800;
521 pformat->u3.dwGBitMask = 0x000007C0;
522 pformat->u4.dwBBitMask = 0x0000003E;
523 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
524 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
525 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
528 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
529 pformat->dwFlags = DDPF_RGB;
530 pformat->u1.dwRGBBitCount = 8;
531 pformat->u2.dwRBitMask = 0x000000E0;
532 pformat->u3.dwGBitMask = 0x0000001C;
533 pformat->u4.dwBBitMask = 0x00000003;
534 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
535 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
536 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
538 TRACE("Enumerating Paletted (8)\n");
539 pformat->dwFlags = DDPF_PALETTEINDEXED8;
540 pformat->u1.dwRGBBitCount = 8;
541 pformat->u2.dwRBitMask = 0x00000000;
542 pformat->u3.dwGBitMask = 0x00000000;
543 pformat->u4.dwBBitMask = 0x00000000;
544 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
545 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
546 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
548 TRACE("End of enumeration\n");
554 d3ddevice_find(IDirectDrawImpl *d3d,
555 LPD3DFINDDEVICESEARCH lpD3DDFS,
556 LPD3DFINDDEVICERESULT lplpD3DDevice)
560 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
561 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
562 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
563 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
565 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
566 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
567 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
568 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
569 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
570 TRACE(" no match for this GUID.\n");
571 return DDERR_INVALIDPARAMS;
575 /* Now return our own GUID */
576 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
577 fill_opengl_caps(&desc);
578 lplpD3DDevice->ddHwDesc = desc;
579 lplpD3DDevice->ddSwDesc = desc;
581 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
587 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
588 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
591 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
592 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
593 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
597 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
598 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
601 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
602 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
603 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
607 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
608 D3DRENDERSTATETYPE dwRenderStateType,
611 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
612 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
614 /* Call the render state functions */
615 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
616 set_render_state(This, dwRenderStateType, &This->state_block);
622 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
623 D3DRENDERSTATETYPE dwRenderStateType,
624 LPDWORD lpdwRenderState)
626 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
627 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
629 /* Call the render state functions */
630 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
632 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
638 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
639 D3DLIGHTSTATETYPE dwLightStateType,
642 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
644 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
646 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
647 TRACE("Unexpected Light State Type\n");
648 return DDERR_INVALIDPARAMS;
650 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
651 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
658 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
660 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
661 switch (dwLightState) {
663 ERR("DDCOLOR_MONO should not happen!\n");
666 /* We are already in this mode */
669 ERR("Unknown color model!\n");
673 D3DRENDERSTATETYPE rs;
674 switch (dwLightStateType) {
676 case D3DLIGHTSTATE_AMBIENT: /* 2 */
677 rs = D3DRENDERSTATE_AMBIENT;
679 case D3DLIGHTSTATE_FOGMODE: /* 4 */
680 rs = D3DRENDERSTATE_FOGVERTEXMODE;
682 case D3DLIGHTSTATE_FOGSTART: /* 5 */
683 rs = D3DRENDERSTATE_FOGSTART;
685 case D3DLIGHTSTATE_FOGEND: /* 6 */
686 rs = D3DRENDERSTATE_FOGEND;
688 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
689 rs = D3DRENDERSTATE_FOGDENSITY;
691 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
692 rs = D3DRENDERSTATE_COLORVERTEX;
698 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
705 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
708 case D3DPT_POINTLIST:
709 TRACE("Start POINTS\n");
714 TRACE("Start LINES\n");
718 case D3DPT_LINESTRIP:
719 TRACE("Start LINE_STRIP\n");
720 glBegin(GL_LINE_STRIP);
723 case D3DPT_TRIANGLELIST:
724 TRACE("Start TRIANGLES\n");
725 glBegin(GL_TRIANGLES);
728 case D3DPT_TRIANGLESTRIP:
729 TRACE("Start TRIANGLE_STRIP\n");
730 glBegin(GL_TRIANGLE_STRIP);
733 case D3DPT_TRIANGLEFAN:
734 TRACE("Start TRIANGLE_FAN\n");
735 glBegin(GL_TRIANGLE_FAN);
739 FIXME("Unhandled primitive %08x\n", d3dpt);
744 /* This function calculate the Z coordinate from Zproj */
745 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
748 /* Assume that X = Y = 0 and W = 1 */
749 a = This->proj_mat->_33;
750 b = This->proj_mat->_34;
751 c = This->proj_mat->_43;
752 d = This->proj_mat->_44;
753 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
754 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
755 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
757 return (d*Zproj - c) / (a - b*Zproj);
760 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
763 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
765 for (i = 0; i < 3; i++) {
766 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
768 for (elt = 0; elt < 0x10000; elt++) {
769 /* We apply the fog transformation and cache the result */
770 DWORD fog_intensity = elt & 0xFF;
771 DWORD vertex_color = (elt >> 8) & 0xFF;
772 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
777 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
778 BOOLEAN vertex_transformed,
779 BOOLEAN vertex_lit) {
780 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
782 /* Puts GL in the correct lighting / transformation mode */
783 if ((vertex_transformed == FALSE) &&
784 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
785 /* Need to put the correct transformation again if we go from Transformed
786 vertices to non-transformed ones.
788 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
789 This->world_mat, This->view_mat, This->proj_mat);
790 glThis->transform_state = GL_TRANSFORM_NORMAL;
792 } else if ((vertex_transformed == TRUE) &&
793 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
794 /* Set our orthographic projection */
795 glThis->transform_state = GL_TRANSFORM_ORTHO;
796 d3ddevice_set_ortho(This);
799 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
800 if no fogging state change occured */
801 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
802 if (vertex_transformed == TRUE) {
804 /* Now check if our fog_table still corresponds to the current vertex color.
805 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
806 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
807 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
808 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
809 /* We need to rebuild our fog table.... */
810 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
813 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
814 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
815 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
816 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
817 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
819 if (vertex_lit == FALSE) {
820 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
821 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
823 /* Special case of 'pixel fog' */
824 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
825 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
836 /* Handle the 'no-normal' case */
837 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
838 glEnable(GL_LIGHTING);
840 glDisable(GL_LIGHTING);
842 /* Handle the code for pre-vertex material properties */
843 if (vertex_transformed == FALSE) {
844 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
845 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
846 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
847 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
848 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
849 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
850 glEnable(GL_COLOR_MATERIAL);
857 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
858 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
860 D3DDRAWPRIMITIVESTRIDEDDATA strided;
864 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
865 strided.position.dwStride = sizeof(D3DVERTEX);
866 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
867 strided.normal.dwStride = sizeof(D3DVERTEX);
868 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
869 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
870 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
873 case D3DVT_LVERTEX: {
874 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
875 strided.position.dwStride = sizeof(D3DLVERTEX);
876 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
877 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
878 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
879 strided.specular.dwStride = sizeof(D3DLVERTEX);
880 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
881 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
882 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
885 case D3DVT_TLVERTEX: {
886 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
887 strided.position.dwStride = sizeof(D3DTLVERTEX);
888 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
889 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
890 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
891 strided.specular.dwStride = sizeof(D3DTLVERTEX);
892 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
893 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
894 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
898 FIXME("Unhandled vertex type %08x\n", d3dvt);
904 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
905 D3DPRIMITIVETYPE d3dptPrimitiveType,
906 D3DVERTEXTYPE d3dvtVertexType,
911 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
913 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
914 if (TRACE_ON(ddraw)) {
915 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
918 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
924 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
925 D3DPRIMITIVETYPE d3dptPrimitiveType,
926 D3DVERTEXTYPE d3dvtVertexType,
933 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
934 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
935 if (TRACE_ON(ddraw)) {
936 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
939 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
945 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
946 LPD3DEXECUTEBUFFERDESC lpDesc,
947 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
950 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
951 IDirect3DExecuteBufferImpl *ret;
954 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
956 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
957 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
959 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
964 /* These are the various handler used in the generic path */
965 inline static void handle_xyz(D3DVALUE *coords) {
968 inline static void handle_xyzrhw(D3DVALUE *coords) {
969 if (coords[3] < 1e-8)
972 GLfloat w = 1.0 / coords[3];
974 glVertex4f(coords[0] * w,
980 inline static void handle_normal(D3DVALUE *coords) {
984 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
985 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
986 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
987 glColor4ub((*color >> 16) & 0xFF,
988 (*color >> 8) & 0xFF,
989 (*color >> 0) & 0xFF,
990 (*color >> 24) & 0xFF);
992 glColor3ub((*color >> 16) & 0xFF,
993 (*color >> 8) & 0xFF,
994 (*color >> 0) & 0xFF);
998 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
999 glColor4ub((*color >> 16) & 0xFF,
1000 (*color >> 8) & 0xFF,
1001 (*color >> 0) & 0xFF,
1002 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1005 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1006 if ((lighted == FALSE) &&
1007 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1008 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1009 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1010 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1011 handle_diffuse_base(sb, color);
1013 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1014 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1015 handle_diffuse_base(sb, color);
1017 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1018 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1019 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1020 handle_diffuse_base(sb, color);
1022 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1023 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1024 handle_diffuse_base(sb, color);
1027 handle_diffuse_base(sb, color);
1031 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1032 if ((lighted == FALSE) &&
1033 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1034 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1035 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1036 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1037 handle_specular_base(sb, color);
1039 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1040 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1041 handle_specular_base(sb, color);
1043 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1044 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1045 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1046 handle_specular_base(sb, color);
1048 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1049 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1050 handle_specular_base(sb, color);
1053 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1056 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1057 if (lighted == TRUE) {
1058 DWORD color = *color_d;
1059 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1060 /* Special case where the specular value is used to do fogging */
1061 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1062 color &= 0xFF000000; /* Only keep the alpha component */
1063 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1064 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1065 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1067 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1068 /* Standard specular value in transformed mode. TODO */
1070 handle_diffuse_base(sb, &color);
1072 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1073 handle_diffuse(sb, color_d, FALSE);
1074 handle_specular(sb, color_s, FALSE);
1076 /* In that case, only put the diffuse color... */
1077 handle_diffuse_base(sb, color_d);
1082 inline static void handle_texture(D3DVALUE *coords) {
1083 glTexCoord2fv(coords);
1085 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1086 /* For the moment, draw only the first texture.. */
1087 if (tex_index == 0) glTexCoord2fv(coords);
1090 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1091 D3DPRIMITIVETYPE d3dptPrimitiveType,
1092 DWORD d3dvtVertexType,
1093 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1094 DWORD dwVertexCount,
1099 BOOLEAN vertex_lighted = FALSE;
1100 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1101 int num_active_stages = 0;
1103 /* This is to prevent 'thread contention' between a thread locking the device and another
1104 doing 3D display on it... */
1105 EnterCriticalSection(&(This->crit));
1108 if (glThis->state == SURFACE_MEMORY_DIRTY) {
1109 This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
1112 glThis->state = SURFACE_GL;
1114 /* Compute the number of active texture stages */
1115 while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
1117 if (TRACE_ON(ddraw)) {
1118 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1121 /* Just a hack for now.. Will have to find better algorithm :-/ */
1122 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1123 vertex_lighted = TRUE;
1125 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1128 draw_primitive_handle_GL_state(This,
1129 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1131 draw_primitive_start_GL(d3dptPrimitiveType);
1133 /* Some fast paths first before the generic case.... */
1134 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1137 for (index = 0; index < dwIndexCount; index++) {
1138 int i = (dwIndices == NULL) ? index : dwIndices[index];
1140 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1141 D3DVALUE *tex_coord =
1142 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1143 D3DVALUE *position =
1144 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1146 handle_normal(normal);
1147 handle_texture(tex_coord);
1148 handle_xyz(position);
1150 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1151 position[0], position[1], position[2],
1152 normal[0], normal[1], normal[2],
1153 tex_coord[0], tex_coord[1]);
1155 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1158 for (index = 0; index < dwIndexCount; index++) {
1159 int i = (dwIndices == NULL) ? index : dwIndices[index];
1161 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1163 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1164 D3DVALUE *tex_coord =
1165 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1166 D3DVALUE *position =
1167 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1169 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1170 handle_texture(tex_coord);
1171 handle_xyzrhw(position);
1173 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1174 position[0], position[1], position[2], position[3],
1175 (*color_d >> 16) & 0xFF,
1176 (*color_d >> 8) & 0xFF,
1177 (*color_d >> 0) & 0xFF,
1178 (*color_d >> 24) & 0xFF,
1179 (*color_s >> 16) & 0xFF,
1180 (*color_s >> 8) & 0xFF,
1181 (*color_s >> 0) & 0xFF,
1182 (*color_s >> 24) & 0xFF,
1183 tex_coord[0], tex_coord[1]);
1185 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1186 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1187 /* This is the 'slow path' but that should support all possible vertex formats out there...
1188 Note that people should write a fast path for all vertex formats out there...
1191 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1192 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1194 for (index = 0; index < dwIndexCount; index++) {
1195 int i = (dwIndices == NULL) ? index : dwIndices[index];
1198 if (d3dvtVertexType & D3DFVF_NORMAL) {
1200 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1201 handle_normal(normal);
1203 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1205 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1207 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1208 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1210 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1212 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1213 handle_specular(&(This->state_block), color_s, vertex_lighted);
1214 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1216 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1217 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1221 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1222 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF000;
1223 if (tex_index >= num_tex_index) {
1224 handle_textures((D3DVALUE *) no_index, tex_stage);
1226 D3DVALUE *tex_coord =
1227 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1228 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1229 handle_textures(tex_coord, tex_stage);
1233 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1234 D3DVALUE *position =
1235 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1236 handle_xyz(position);
1237 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1238 D3DVALUE *position =
1239 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1240 handle_xyzrhw(position);
1243 if (TRACE_ON(ddraw_geom)) {
1246 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1247 D3DVALUE *position =
1248 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1249 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1250 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1251 D3DVALUE *position =
1252 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1253 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1255 if (d3dvtVertexType & D3DFVF_NORMAL) {
1257 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1258 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1260 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1262 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1263 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1264 (*color_d >> 16) & 0xFF,
1265 (*color_d >> 8) & 0xFF,
1266 (*color_d >> 0) & 0xFF,
1267 (*color_d >> 24) & 0xFF);
1269 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1271 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1272 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1273 (*color_s >> 16) & 0xFF,
1274 (*color_s >> 8) & 0xFF,
1275 (*color_s >> 0) & 0xFF,
1276 (*color_s >> 24) & 0xFF);
1278 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1279 D3DVALUE *tex_coord =
1280 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1281 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1282 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1284 TRACE_(ddraw_geom)("\n");
1288 ERR(" matrix weighting not handled yet....\n");
1293 /* Whatever the case, disable the color material stuff */
1294 glDisable(GL_COLOR_MATERIAL);
1299 LeaveCriticalSection(&(This->crit));
1303 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1304 D3DPRIMITIVETYPE d3dptPrimitiveType,
1305 DWORD d3dvtVertexType,
1307 DWORD dwVertexCount,
1310 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1311 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1313 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1314 if (TRACE_ON(ddraw)) {
1315 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1318 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1319 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1325 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1326 D3DPRIMITIVETYPE d3dptPrimitiveType,
1327 DWORD d3dvtVertexType,
1329 DWORD dwVertexCount,
1334 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1335 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1337 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1338 if (TRACE_ON(ddraw)) {
1339 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1342 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1343 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1349 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1350 D3DPRIMITIVETYPE d3dptPrimitiveType,
1352 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1353 DWORD dwVertexCount,
1356 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1358 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1359 if (TRACE_ON(ddraw)) {
1360 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1362 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1368 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1369 D3DPRIMITIVETYPE d3dptPrimitiveType,
1371 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1372 DWORD dwVertexCount,
1377 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1379 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1380 if (TRACE_ON(ddraw)) {
1381 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1384 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1390 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1391 D3DPRIMITIVETYPE d3dptPrimitiveType,
1392 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1393 DWORD dwStartVertex,
1394 DWORD dwNumVertices,
1397 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1398 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1399 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1401 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1402 if (TRACE_ON(ddraw)) {
1403 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1406 if (vb_impl->processed == TRUE) {
1407 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1408 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1410 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1411 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1412 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1414 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1415 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1418 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1419 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1426 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1427 D3DPRIMITIVETYPE d3dptPrimitiveType,
1428 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1429 DWORD dwStartVertex,
1430 DWORD dwNumVertices,
1435 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1436 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1437 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1439 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1440 if (TRACE_ON(ddraw)) {
1441 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1444 if (vb_impl->processed == TRUE) {
1445 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1446 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1448 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1449 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1450 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1452 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1453 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1456 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1457 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1464 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
1468 if (dwMipState == D3DTFP_NONE) {
1469 switch (dwMinState) {
1470 case D3DTFN_POINT: gl_state = GL_NEAREST; break;
1471 case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
1472 default: gl_state = GL_LINEAR; break;
1474 } else if (dwMipState == D3DTFP_POINT) {
1475 switch (dwMinState) {
1476 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
1477 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1478 default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1481 switch (dwMinState) {
1482 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
1483 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1484 default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1491 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1497 gl_state = GL_NEAREST;
1500 gl_state = GL_LINEAR;
1503 gl_state = GL_LINEAR;
1510 convert_tex_address_to_GL(D3DTEXTUREADDRESS dwState)
1514 case D3DTADDRESS_WRAP: gl_state = GL_REPEAT; break;
1515 case D3DTADDRESS_CLAMP: gl_state = GL_CLAMP; break;
1516 case D3DTADDRESS_BORDER: gl_state = GL_CLAMP_TO_EDGE; break;
1517 #if defined(GL_VERSION_1_4)
1518 case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT; break;
1519 #elif defined(GL_ARB_texture_mirrored_repeat)
1520 case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT_ARB; break;
1522 default: gl_state = GL_REPEAT; break;
1527 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1529 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1531 BOOLEAN is_complement = FALSE;
1532 BOOLEAN is_alpha_replicate = FALSE;
1533 BOOLEAN handled = TRUE;
1535 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1539 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1540 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1545 if (tex_op == D3DTOP_SELECTARG2) {
1549 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1550 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1555 if (tex_op == D3DTOP_SELECTARG2) {
1560 if (dwState & D3DTA_COMPLEMENT) {
1561 is_complement = TRUE;
1563 if (dwState & D3DTA_ALPHAREPLICATE) {
1564 is_alpha_replicate = TRUE;
1566 dwState &= D3DTA_SELECTMASK;
1567 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1568 dwState = D3DTA_DIFFUSE;
1572 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1573 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1574 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1575 case D3DTA_TFACTOR: {
1576 /* Get the constant value from the current rendering state */
1578 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1580 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1581 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1582 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1583 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1584 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1586 src = GL_CONSTANT_EXT;
1588 default: src = GL_TEXTURE; handled = FALSE; break;
1592 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1593 if (is_alpha_replicate) {
1594 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1596 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1599 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1600 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1607 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1609 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1612 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1616 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1618 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1620 switch (d3dTexStageStateType) {
1621 #define GEN_CASE(a) case a: type = #a; break
1622 GEN_CASE(D3DTSS_COLOROP);
1623 GEN_CASE(D3DTSS_COLORARG1);
1624 GEN_CASE(D3DTSS_COLORARG2);
1625 GEN_CASE(D3DTSS_ALPHAOP);
1626 GEN_CASE(D3DTSS_ALPHAARG1);
1627 GEN_CASE(D3DTSS_ALPHAARG2);
1628 GEN_CASE(D3DTSS_BUMPENVMAT00);
1629 GEN_CASE(D3DTSS_BUMPENVMAT01);
1630 GEN_CASE(D3DTSS_BUMPENVMAT10);
1631 GEN_CASE(D3DTSS_BUMPENVMAT11);
1632 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1633 GEN_CASE(D3DTSS_ADDRESS);
1634 GEN_CASE(D3DTSS_ADDRESSU);
1635 GEN_CASE(D3DTSS_ADDRESSV);
1636 GEN_CASE(D3DTSS_BORDERCOLOR);
1637 GEN_CASE(D3DTSS_MAGFILTER);
1638 GEN_CASE(D3DTSS_MINFILTER);
1639 GEN_CASE(D3DTSS_MIPFILTER);
1640 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1641 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1642 GEN_CASE(D3DTSS_MAXANISOTROPY);
1643 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1644 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1645 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1647 default: type = "UNKNOWN";
1650 /* Store the values in the state array */
1651 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1652 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1653 /* Some special cases when one state modifies more than one... */
1654 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1655 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1656 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1661 switch (d3dTexStageStateType) {
1662 case D3DTSS_MINFILTER:
1663 case D3DTSS_MIPFILTER:
1664 if (TRACE_ON(ddraw)) {
1665 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1666 switch ((D3DTEXTUREMINFILTER) dwState) {
1667 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1668 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1669 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1672 switch ((D3DTEXTUREMIPFILTER) dwState) {
1673 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1674 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1675 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1676 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1681 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1682 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
1683 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
1686 case D3DTSS_MAGFILTER:
1687 if (TRACE_ON(ddraw)) {
1688 switch ((D3DTEXTUREMAGFILTER) dwState) {
1689 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1690 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1691 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1694 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1697 case D3DTSS_ADDRESS:
1698 case D3DTSS_ADDRESSU:
1699 case D3DTSS_ADDRESSV: {
1700 GLenum arg = convert_tex_address_to_GL(dwState);
1702 switch ((D3DTEXTUREADDRESS) dwState) {
1703 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1704 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1705 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1706 #if defined(GL_VERSION_1_4)
1707 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1708 #elif defined(GL_ARB_texture_mirrored_repeat)
1709 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1711 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1714 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1715 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1716 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1717 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1718 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1719 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1722 case D3DTSS_ALPHAOP:
1723 case D3DTSS_COLOROP: {
1725 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1730 #define GEN_CASE(a) case a: value = #a; break
1731 GEN_CASE(D3DTOP_DISABLE);
1732 GEN_CASE(D3DTOP_SELECTARG1);
1733 GEN_CASE(D3DTOP_SELECTARG2);
1734 GEN_CASE(D3DTOP_MODULATE);
1735 GEN_CASE(D3DTOP_MODULATE2X);
1736 GEN_CASE(D3DTOP_MODULATE4X);
1737 GEN_CASE(D3DTOP_ADD);
1738 GEN_CASE(D3DTOP_ADDSIGNED);
1739 GEN_CASE(D3DTOP_ADDSIGNED2X);
1740 GEN_CASE(D3DTOP_SUBTRACT);
1741 GEN_CASE(D3DTOP_ADDSMOOTH);
1742 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1743 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1744 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1745 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1746 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1747 GEN_CASE(D3DTOP_PREMODULATE);
1748 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1749 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1750 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1751 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1752 GEN_CASE(D3DTOP_BUMPENVMAP);
1753 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1754 GEN_CASE(D3DTOP_DOTPRODUCT3);
1755 GEN_CASE(D3DTOP_FORCE_DWORD);
1757 default: value = "UNKNOWN";
1760 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1761 glDisable(GL_TEXTURE_2D);
1762 TRACE(" disabling 2D texturing.\n");
1764 /* Re-enable texturing */
1765 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1766 glEnable(GL_TEXTURE_2D);
1767 TRACE(" enabling 2D texturing.\n");
1770 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1771 if (dwState != D3DTOP_DISABLE) {
1772 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1775 /* Now set up the operand correctly */
1777 case D3DTOP_DISABLE:
1778 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1779 and it works, so ignore this op */
1780 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1783 case D3DTOP_SELECTARG1:
1784 case D3DTOP_SELECTARG2:
1785 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1788 case D3DTOP_MODULATE4X:
1789 scale = scale * 2; /* Drop through */
1790 case D3DTOP_MODULATE2X:
1791 scale = scale * 2; /* Drop through */
1792 case D3DTOP_MODULATE:
1793 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1797 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1800 case D3DTOP_ADDSIGNED2X:
1801 scale = scale * 2; /* Drop through */
1802 case D3DTOP_ADDSIGNED:
1803 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1806 /* For the four blending modes, use the Arg2 parameter */
1807 case D3DTOP_BLENDDIFFUSEALPHA:
1808 case D3DTOP_BLENDTEXTUREALPHA:
1809 case D3DTOP_BLENDFACTORALPHA:
1810 case D3DTOP_BLENDCURRENTALPHA: {
1811 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1814 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1815 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1816 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1817 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1820 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1821 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1822 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1823 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1824 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1833 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1834 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1835 /* Switch the arguments if needed... */
1836 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1837 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1838 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1840 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1841 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1844 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1845 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1847 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1848 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1854 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1855 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1857 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1859 TRACE(" Stage type is : %s => %s\n", type, value);
1861 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1865 case D3DTSS_COLORARG1:
1866 case D3DTSS_COLORARG2:
1867 case D3DTSS_ALPHAARG1:
1868 case D3DTSS_ALPHAARG2: {
1869 const char *value, *value_comp = "", *value_alpha = "";
1871 D3DTEXTUREOP tex_op;
1873 switch (dwState & D3DTA_SELECTMASK) {
1874 #define GEN_CASE(a) case a: value = #a; break
1875 GEN_CASE(D3DTA_DIFFUSE);
1876 GEN_CASE(D3DTA_CURRENT);
1877 GEN_CASE(D3DTA_TEXTURE);
1878 GEN_CASE(D3DTA_TFACTOR);
1879 GEN_CASE(D3DTA_SPECULAR);
1881 default: value = "UNKNOWN";
1883 if (dwState & D3DTA_COMPLEMENT) {
1884 value_comp = " | D3DTA_COMPLEMENT";
1886 if (dwState & D3DTA_ALPHAREPLICATE) {
1887 value_alpha = " | D3DTA_ALPHAREPLICATE";
1890 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1891 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1893 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1896 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
1899 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1901 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1905 case D3DTSS_MIPMAPLODBIAS: {
1906 D3DVALUE value = *((D3DVALUE *) &dwState);
1907 BOOLEAN handled = TRUE;
1913 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1915 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1919 case D3DTSS_MAXMIPLEVEL:
1921 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
1923 FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1927 case D3DTSS_BORDERCOLOR: {
1930 color[0] = ((dwState >> 16) & 0xFF) / 255.0;
1931 color[1] = ((dwState >> 8) & 0xFF) / 255.0;
1932 color[2] = ((dwState >> 0) & 0xFF) / 255.0;
1933 color[3] = ((dwState >> 24) & 0xFF) / 255.0;
1935 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
1937 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1938 ((dwState >> 16) & 0xFF),
1939 ((dwState >> 8) & 0xFF),
1940 ((dwState >> 0) & 0xFF),
1941 ((dwState >> 24) & 0xFF));
1944 case D3DTSS_TEXCOORDINDEX: {
1945 BOOLEAN handled = TRUE;
1948 switch (dwState & 0xFFFF0000) {
1949 #define GEN_CASE(a) case a: value = #a; break
1950 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1951 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1952 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1953 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1955 default: value = "UNKNOWN";
1957 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1961 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1963 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1967 case D3DTSS_TEXTURETRANSFORMFLAGS: {
1968 const char *projected = "", *value;
1969 BOOLEAN handled = TRUE;
1970 switch (dwState & 0xFF) {
1971 #define GEN_CASE(a) case a: value = #a; break
1972 GEN_CASE(D3DTTFF_DISABLE);
1973 GEN_CASE(D3DTTFF_COUNT1);
1974 GEN_CASE(D3DTTFF_COUNT2);
1975 GEN_CASE(D3DTTFF_COUNT3);
1976 GEN_CASE(D3DTTFF_COUNT4);
1978 default: value = "UNKNOWN";
1980 if (dwState & D3DTTFF_PROJECTED) {
1981 projected = " | D3DTTFF_PROJECTED";
1985 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
1986 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
1989 if (handled == TRUE) {
1990 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1992 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
1997 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2007 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2009 LPDIRECTDRAWSURFACE7 lpTexture2)
2011 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2013 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2015 if (dwStage > 0) return DD_OK;
2017 if (This->current_texture[dwStage] != NULL) {
2018 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2022 if (lpTexture2 == NULL) {
2023 This->current_texture[dwStage] = NULL;
2025 TRACE(" disabling 2D texturing.\n");
2026 glBindTexture(GL_TEXTURE_2D, 0);
2027 glDisable(GL_TEXTURE_2D);
2029 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2030 GLint max_mip_level;
2033 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
2035 if (This->current_texture[dwStage] == tex_impl) {
2036 /* No need to do anything as the texture did not change. */
2039 This->current_texture[dwStage] = tex_impl;
2041 if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2042 /* Do not re-enable texturing if it was disabled due to the COLOROP code */
2043 glEnable(GL_TEXTURE_2D);
2044 TRACE(" enabling 2D texturing.\n");
2046 gltex_upload_texture(tex_impl);
2048 if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
2051 max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
2054 /* Now we need to reset all glTexParameter calls for this particular texture... */
2055 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2056 convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
2057 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2058 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
2059 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
2060 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
2061 convert_tex_address_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1]));
2062 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
2063 convert_tex_address_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1]));
2064 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
2065 color[0] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 16) & 0xFF) / 255.0;
2066 color[1] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 8) & 0xFF) / 255.0;
2067 color[2] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 0) & 0xFF) / 255.0;
2068 color[3] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 24) & 0xFF) / 255.0;
2069 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
2077 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2078 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2080 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2081 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2083 fill_opengl_caps_7(lpD3DHELDevDesc);
2085 TRACE(" returning caps : no dump function yet.\n");
2091 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2092 LPD3DMATERIAL7 lpMat)
2094 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2095 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2097 if (TRACE_ON(ddraw)) {
2098 TRACE(" material is : \n");
2099 dump_D3DMATERIAL7(lpMat);
2102 This->current_material = *lpMat;
2104 glMaterialfv(GL_FRONT_AND_BACK,
2106 (float *) &(This->current_material.u.diffuse));
2107 glMaterialfv(GL_FRONT_AND_BACK,
2109 (float *) &(This->current_material.u1.ambient));
2110 glMaterialfv(GL_FRONT_AND_BACK,
2112 (float *) &(This->current_material.u2.specular));
2113 glMaterialfv(GL_FRONT_AND_BACK,
2115 (float *) &(This->current_material.u3.emissive));
2116 glMaterialf(GL_FRONT_AND_BACK,
2118 This->current_material.u4.power); /* Not sure about this... */
2125 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2127 LPD3DLIGHT7 lpLight)
2129 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2130 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2131 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2133 if (TRACE_ON(ddraw)) {
2134 TRACE(" setting light : \n");
2135 dump_D3DLIGHT7(lpLight);
2138 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2139 This->set_lights |= 0x00000001 << dwLightIndex;
2140 This->light_parameters[dwLightIndex] = *lpLight;
2142 /* Some checks to print out nice warnings :-) */
2143 switch (lpLight->dltType) {
2144 case D3DLIGHT_DIRECTIONAL:
2145 case D3DLIGHT_POINT:
2146 /* These are handled properly... */
2150 if ((lpLight->dvTheta != 0.0) ||
2151 (lpLight->dvTheta != lpLight->dvPhi)) {
2152 ERR("dvTheta not fully supported yet !\n");
2157 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2160 /* This will force the Light setting on next drawing of primitives */
2161 glThis->transform_state = GL_TRANSFORM_NONE;
2167 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2171 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2172 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2174 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2177 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2178 /* Set the default parameters.. */
2179 TRACE(" setting default light parameters...\n");
2180 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2182 glEnable(GL_LIGHT0 + dwLightIndex);
2183 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2184 /* This light gets active... Need to update its parameters to GL before the next drawing */
2185 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2187 This->active_lights |= 0x00000001 << dwLightIndex;
2188 glThis->transform_state = GL_TRANSFORM_NONE;
2191 glDisable(GL_LIGHT0 + dwLightIndex);
2192 This->active_lights &= ~(0x00000001 << dwLightIndex);
2199 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2201 ICOM_THIS(IDirect3DDeviceImpl,iface);
2202 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2204 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2206 if (dwIndex >= This->max_clipping_planes) {
2207 return DDERR_INVALIDPARAMS;
2210 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2212 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2214 /* This is to force the reset of the transformation matrices on the next drawing.
2215 * This is needed to use the correct matrices for the various clipping planes.
2217 glThis->transform_state = GL_TRANSFORM_NONE;
2223 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2224 LPD3DVIEWPORT7 lpData)
2226 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2227 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2229 if (TRACE_ON(ddraw)) {
2230 TRACE(" viewport is : \n");
2231 TRACE(" - dwX = %ld dwY = %ld\n",
2232 lpData->dwX, lpData->dwY);
2233 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2234 lpData->dwWidth, lpData->dwHeight);
2235 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2236 lpData->dvMinZ, lpData->dvMaxZ);
2238 This->active_viewport = *lpData;
2242 /* Set the viewport */
2243 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2244 glViewport(lpData->dwX,
2245 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2246 lpData->dwWidth, lpData->dwHeight);
2253 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2254 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2256 # define XCAST(fun) (void*)
2259 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2261 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2262 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2263 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2264 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2265 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2266 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2267 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2268 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2269 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2270 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2271 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2272 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2273 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2274 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2275 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2276 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2277 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2278 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2279 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2280 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2281 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2282 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2283 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2284 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2285 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2286 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2287 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2288 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2289 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2290 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2291 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2292 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2293 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2294 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2295 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2296 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2297 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2298 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2299 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2300 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2301 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2302 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2303 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2304 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2305 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2306 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2307 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2308 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2309 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2310 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2313 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2318 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2319 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2321 # define XCAST(fun) (void*)
2324 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2326 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2327 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2328 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2329 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2330 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2331 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2332 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2333 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2334 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2335 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2336 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2337 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2338 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2339 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2340 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2341 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2342 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2343 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2344 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2345 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2346 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2347 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2348 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2349 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2350 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2351 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2352 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2353 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2354 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2355 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2356 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2357 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2358 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2359 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2360 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2361 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2362 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2363 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2364 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2365 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2366 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2367 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2368 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2371 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2376 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2377 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2379 # define XCAST(fun) (void*)
2382 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2384 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2385 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2386 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2387 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2388 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2389 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2390 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2391 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2392 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2393 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2394 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2395 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2396 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2397 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2398 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2399 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2400 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2401 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2402 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2403 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2404 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2405 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2406 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2407 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2408 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2409 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2410 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2411 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2412 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2413 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2414 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2415 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2416 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2417 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2420 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2425 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2426 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2428 # define XCAST(fun) (void*)
2431 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2433 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2434 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2435 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2436 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2437 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2438 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2439 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2440 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2441 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2442 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2443 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2444 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2445 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2446 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2447 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2448 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2449 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2450 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2451 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2452 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2453 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2454 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2455 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2458 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2462 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2470 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2472 GLfloat old_z_clear_value;
2473 GLbitfield bitfield = 0;
2474 GLint old_stencil_clear_value;
2475 GLfloat old_color_clear_value[4];
2479 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2480 if (TRACE_ON(ddraw)) {
2483 TRACE(" rectangles : \n");
2484 for (i = 0; i < dwCount; i++) {
2485 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2491 /* Not sure if this is really needed... */
2495 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2496 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2500 /* Clears the screen */
2503 if (glThis->state == SURFACE_MEMORY_DIRTY) {
2504 /* TODO: optimize here the case where Clear changes all the screen... */
2505 This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
2507 glThis->state = SURFACE_GL;
2509 if (dwFlags & D3DCLEAR_ZBUFFER) {
2510 bitfield |= GL_DEPTH_BUFFER_BIT;
2511 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2512 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2513 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2515 TRACE(" depth value : %f\n", dvZ);
2517 if (dwFlags & D3DCLEAR_STENCIL) {
2518 bitfield |= GL_STENCIL_BUFFER_BIT;
2519 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2520 glClearStencil(dwStencil);
2521 TRACE(" stencil value : %ld\n", dwStencil);
2523 if (dwFlags & D3DCLEAR_TARGET) {
2524 bitfield |= GL_COLOR_BUFFER_BIT;
2525 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2526 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2527 ((dwColor >> 8) & 0xFF) / 255.0,
2528 ((dwColor >> 0) & 0xFF) / 255.0,
2529 ((dwColor >> 24) & 0xFF) / 255.0);
2530 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2533 glEnable(GL_SCISSOR_TEST);
2534 for (i = 0; i < dwCount; i++) {
2535 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2536 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2539 glDisable(GL_SCISSOR_TEST);
2541 if (dwFlags & D3DCLEAR_ZBUFFER) {
2543 glClearDepth(old_z_clear_value);
2545 if (dwFlags & D3DCLEAR_STENCIL) {
2546 bitfield |= GL_STENCIL_BUFFER_BIT;
2547 glClearStencil(old_stencil_clear_value);
2549 if (dwFlags & D3DCLEAR_TARGET) {
2550 bitfield |= GL_COLOR_BUFFER_BIT;
2551 glClearColor(old_color_clear_value[0],
2552 old_color_clear_value[1],
2553 old_color_clear_value[2],
2554 old_color_clear_value[3]);
2563 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2564 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2565 DWORD dwFlags, LPDDBLTFX lpbltfx)
2567 if (dwFlags & DDBLT_COLORFILL) {
2568 /* This is easy to handle for the D3D Device... */
2569 DWORD color = lpbltfx->u5.dwFillColor;
2572 TRACE(" executing D3D Device override.\n");
2575 rect.u1.x1 = rdst->left;
2576 rect.u2.y1 = rdst->top;
2577 rect.u3.x2 = rdst->right;
2578 rect.u4.y2 = rdst->bottom;
2580 d3ddevice_clear(This->d3ddevice, rdst != NULL ? 1 : 0, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2583 return DDERR_INVALIDPARAMS;
2587 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2588 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2589 LPRECT rsrc, DWORD trans)
2591 return DDERR_INVALIDPARAMS;
2595 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2597 GLfloat height, width;
2598 GLfloat trans_mat[16];
2600 width = This->surface->surface_desc.dwWidth;
2601 height = This->surface->surface_desc.dwHeight;
2603 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2604 to OpenGL screen coordinates (ie the upper left corner is not the same).
2605 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2606 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2607 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2608 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
2609 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
2610 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
2612 glMatrixMode(GL_MODELVIEW);
2614 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2615 Correctness Tips section).
2617 Basically, from what I understood, if the game does not filter the font texture,
2618 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2619 one and we will have strange artifacts (as the rounding and stuff may give different results
2620 for different pixels, ie sometimes take the left pixel, sometimes the right).
2622 glTranslatef(0.375, 0.375, 0);
2623 glMatrixMode(GL_PROJECTION);
2624 glLoadMatrixf(trans_mat);
2628 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2629 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2631 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2632 glMatrixMode(GL_MODELVIEW);
2633 glLoadMatrixf((float *) view_mat);
2635 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
2636 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
2639 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
2640 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
2643 plane[0] = This->clipping_planes[i].plane[0];
2644 plane[1] = This->clipping_planes[i].plane[1];
2645 plane[2] = This->clipping_planes[i].plane[2];
2646 plane[3] = This->clipping_planes[i].plane[3];
2648 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
2652 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
2656 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
2657 if (runner & This->active_lights) {
2658 switch (This->light_parameters[i].dltType) {
2659 case D3DLIGHT_DIRECTIONAL: {
2661 float cut_off = 180.0;
2663 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2664 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2665 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2666 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2668 direction[0] = This->light_parameters[i].dvDirection.u1.x;
2669 direction[1] = This->light_parameters[i].dvDirection.u2.y;
2670 direction[2] = This->light_parameters[i].dvDirection.u3.z;
2672 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
2675 case D3DLIGHT_POINT: {
2677 float cut_off = 180.0;
2679 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2680 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2681 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2682 position[0] = This->light_parameters[i].dvPosition.u1.x;
2683 position[1] = This->light_parameters[i].dvPosition.u2.y;
2684 position[2] = This->light_parameters[i].dvPosition.u3.z;
2686 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2687 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2688 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2689 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2690 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2693 case D3DLIGHT_SPOT: {
2696 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
2698 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2699 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2700 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2702 direction[0] = This->light_parameters[i].dvDirection.u1.x;
2703 direction[1] = This->light_parameters[i].dvDirection.u2.y;
2704 direction[2] = This->light_parameters[i].dvDirection.u3.z;
2706 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
2707 position[0] = This->light_parameters[i].dvPosition.u1.x;
2708 position[1] = This->light_parameters[i].dvPosition.u2.y;
2709 position[2] = This->light_parameters[i].dvPosition.u3.z;
2711 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2712 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2713 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2714 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2715 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2716 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
2720 /* No warning here as it's already done at light setting */
2727 glMultMatrixf((float *) world_mat);
2729 if ((matrices & PROJMAT_CHANGED) != 0) {
2730 glMatrixMode(GL_PROJECTION);
2731 glLoadMatrixf((float *) proj_mat);
2736 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2738 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2739 DWORD tex_mat, tex_stage;
2740 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) != 0) {
2741 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2742 /* This will force an update of the transform state at the next drawing. */
2743 glThis->transform_state = GL_TRANSFORM_NONE;
2746 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
2747 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
2750 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
2751 if (matrices & tex_mat) {
2752 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
2753 if (tex_stage == 0) {
2754 /* No multi-texturing support for now ... */
2755 glMatrixMode(GL_TEXTURE);
2756 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
2759 glMatrixMode(GL_TEXTURE);
2768 /* TODO for both these functions :
2769 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2770 by other OpenGL code in D3D
2771 - handle the case where no 'Begin / EndScene' was done between two locks
2772 - handle the rectangles in the unlock too
2773 - handle pitch correctly...
2775 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2777 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2778 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2781 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2783 if ((gl_d3d_dev->front_state != SURFACE_GL) &&
2784 (gl_d3d_dev->front_lock_surf != This)) {
2785 ERR("Change of front buffer.. Expect graphic corruptions !\n");
2787 gl_d3d_dev->front_lock_surf = This;
2788 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2790 if ((gl_d3d_dev->state != SURFACE_GL) &&
2791 (gl_d3d_dev->lock_surf != This)) {
2792 ERR("Change of back buffer.. Expect graphic corruptions !\n");
2794 gl_d3d_dev->lock_surf = This;
2796 ERR("Wrong surface type for locking !\n");
2800 /* Try to acquire the device critical section */
2801 EnterCriticalSection(&(d3d_dev->crit));
2803 if (((is_front == TRUE) && (gl_d3d_dev->front_state == SURFACE_GL)) ||
2804 ((is_front == FALSE) && (gl_d3d_dev->state == SURFACE_GL))) {
2805 /* If the surface is already in memory, no need to do anything here... */
2807 GLenum buffer_color;
2812 TRACE(" copying frame buffer to main memory.\n");
2814 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2815 may only write to the device... But when we will blit it back to the screen, we need
2816 also to blit correctly the parts the application did not overwrite... */
2818 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2819 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2820 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2821 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2822 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2823 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2824 buffer_color = GL_RGB;
2825 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2826 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2827 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2828 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2829 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2830 buffer_type = GL_UNSIGNED_BYTE;
2831 buffer_color = GL_BGRA;
2832 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
2834 ERR(" unsupported pixel format at device locking.\n");
2840 if (is_front == TRUE)
2841 /* Application wants to lock the front buffer */
2842 glReadBuffer(GL_FRONT);
2844 /* Application wants to lock the back buffer */
2845 glReadBuffer(GL_BACK);
2847 /* Just a hack while waiting for proper rectangle support */
2849 if (pRect == NULL) {
2852 loc_rect.bottom = This->surface_desc.dwHeight;
2853 loc_rect.right = This->surface_desc.dwWidth;
2858 dst = ((char *)This->surface_desc.lpSurface) +
2859 (loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
2860 for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
2861 y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
2863 glReadPixels(loc_rect.left, y,
2864 loc_rect.right - loc_rect.left, 1,
2865 buffer_color, buffer_type, dst);
2866 dst += This->surface_desc.u1.lPitch;
2869 glPixelStorei(GL_PACK_SWAP_BYTES, FALSE);
2872 gl_d3d_dev->front_state = SURFACE_MEMORY;
2874 gl_d3d_dev->state = SURFACE_MEMORY;
2877 /* I keep this code here as it's very useful to debug :-) */
2879 static int flush_count = 0;
2883 if ((++flush_count % 50) == 0) {
2884 sprintf(buf, "lock_%06d.pnm", flush_count);
2885 f = fopen(buf, "wb");
2886 DDRAW_dump_surface_to_disk(This, f);
2895 #define UNLOCK_TEX_SIZE 256
2897 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
2899 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2900 GLint depth_test, alpha_test, cull_face, lighting, tex_env, blend, stencil_test, fog;
2901 GLuint initial_texture;
2904 BOOLEAN initial = FALSE;
2906 /* Note : no need here to lock the 'device critical section' as we are already protected by
2907 the GL critical section. */
2911 loc_rect.bottom = surf->surface_desc.dwHeight;
2912 loc_rect.right = surf->surface_desc.dwWidth;
2914 TRACE(" flushing memory back to the frame-buffer (%ld,%ld) x (%ld,%ld).\n", loc_rect.top, loc_rect.left, loc_rect.right, loc_rect.bottom);
2916 glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
2917 if (gl_d3d_dev->unlock_tex == 0) {
2918 glGenTextures(1, &gl_d3d_dev->unlock_tex);
2919 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2921 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2922 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2924 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2927 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
2928 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != D3D_OK) {
2929 ERR(" unsupported pixel format at frame buffer flush.\n");
2930 glBindTexture(GL_TEXTURE_2D, initial_texture);
2934 glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2935 glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2936 glGetIntegerv(GL_STENCIL_TEST, &stencil_test);
2937 glGetIntegerv(GL_CULL_FACE, &cull_face);
2938 glGetIntegerv(GL_LIGHTING, &lighting);
2939 glGetIntegerv(GL_BLEND, &blend);
2940 glGetIntegerv(GL_TEXTURE_2D, &tex_state);
2941 glGetIntegerv(GL_FOG, &fog);
2942 glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2943 glMatrixMode(GL_TEXTURE);
2945 /* TODO: scissor test if ever we use it ! */
2947 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2948 d3ddevice_set_ortho(d3d_dev);
2950 glDisable(GL_DEPTH_TEST);
2951 glEnable(GL_TEXTURE_2D);
2952 glEnable(GL_SCISSOR_TEST);
2953 glDepthRange(0.0, 1.0);
2954 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
2955 glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
2956 loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
2957 glDisable(GL_LIGHTING);
2958 glDisable(GL_CULL_FACE);
2959 glDisable(GL_ALPHA_TEST);
2960 glDisable(GL_STENCIL_TEST);
2961 glDisable(GL_BLEND);
2963 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
2965 for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
2966 for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
2967 /* First, upload the texture... */
2970 flush_rect.left = x;
2972 flush_rect.right = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth) ? surf->surface_desc.dwWidth : (x + UNLOCK_TEX_SIZE);
2973 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? surf->surface_desc.dwHeight : (y + UNLOCK_TEX_SIZE);
2975 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
2978 glColor3ub(0xFF, 0xFF, 0xFF);
2979 glTexCoord2f(0.0, 0.0);
2980 glVertex3d(x, y, 0.5);
2981 glTexCoord2f(1.0, 0.0);
2982 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
2983 glTexCoord2f(1.0, 1.0);
2984 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
2985 glTexCoord2f(0.0, 1.0);
2986 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
2991 upload_surface_to_tex_memory_release();
2993 /* And restore all the various states modified by this code */
2994 if (depth_test != 0) glEnable(GL_DEPTH_TEST);
2995 if (lighting != 0) glEnable(GL_LIGHTING);
2996 if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
2997 if (stencil_test != 0) glEnable(GL_STENCIL_TEST);
2998 if (cull_face != 0) glEnable(GL_CULL_FACE);
2999 if (blend != 0) glEnable(GL_BLEND);
3000 if (fog != 0) glEnable(GL_FOG);
3001 glBindTexture(GL_TEXTURE_2D, initial_texture);
3002 if (tex_state == 0) glDisable(GL_TEXTURE_2D);
3003 glDisable(GL_SCISSOR_TEST);
3004 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3005 glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
3006 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
3007 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
3008 glViewport(d3d_dev->active_viewport.dwX,
3009 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
3010 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
3011 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
3013 /* I keep this code here as it's very useful to debug :-) */
3015 static int flush_count = 0;
3019 if ((++flush_count % 50) == 0) {
3020 sprintf(buf, "flush_%06d.pnm", flush_count);
3021 f = fopen(buf, "wb");
3022 DDRAW_dump_surface_to_disk(surf, f);
3028 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3031 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3032 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3034 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3036 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3039 ERR("Wrong surface type for locking !\n");
3042 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3043 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3044 if (is_front == TRUE) {
3047 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3048 glDrawBuffer(GL_FRONT);
3049 d3d_dev->flush_to_framebuffer(d3d_dev, pRect, gl_d3d_dev->front_lock_surf);
3050 glDrawBuffer(prev_draw);
3053 gl_d3d_dev->state = SURFACE_MEMORY_DIRTY;
3057 /* And 'frees' the device critical section */
3058 LeaveCriticalSection(&(d3d_dev->crit));
3062 apply_texture_state(IDirect3DDeviceImpl *This)
3066 /* Initialize texture stages states */
3067 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3068 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3069 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3070 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3071 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3078 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface)
3080 IDirect3DDeviceImpl *object;
3081 IDirect3DDeviceGLImpl *gl_object;
3082 IDirectDrawSurfaceImpl *surf;
3087 XVisualInfo template;
3088 GLenum buffer = GL_FRONT;
3090 GLint max_clipping_planes = 0;
3092 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3093 if (object == NULL) return DDERR_OUTOFMEMORY;
3095 gl_object = (IDirect3DDeviceGLImpl *) object;
3099 object->surface = surface;
3100 object->set_context = set_context;
3101 object->clear = d3ddevice_clear;
3102 object->set_matrices = d3ddevice_set_matrices;
3103 object->matrices_updated = d3ddevice_matrices_updated;
3104 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3106 InitializeCriticalSection(&(object->crit));
3108 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3110 device_context = GetDC(surface->ddraw_owner->window);
3111 gl_object->display = get_display(device_context);
3112 gl_object->drawable = get_drawable(device_context);
3113 ReleaseDC(surface->ddraw_owner->window,device_context);
3116 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3117 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3119 HeapFree(GetProcessHeap(), 0, object);
3120 ERR("No visual found !\n");
3122 return DDERR_INVALIDPARAMS;
3124 TRACE(" visual found\n");
3127 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3130 if (gl_object->gl_context == NULL) {
3131 HeapFree(GetProcessHeap(), 0, object);
3132 ERR("Error in context creation !\n");
3134 return DDERR_INVALIDPARAMS;
3136 TRACE(" context created (%p)\n", gl_object->gl_context);
3139 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3140 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3141 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3142 surf->aux_ctx = (LPVOID) object;
3143 surf->aux_data = (LPVOID) gl_object->drawable;
3144 surf->aux_flip = opengl_flip;
3149 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3151 TRACE(" no double buffering : drawing on the front buffer\n");
3155 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3156 IDirectDrawSurfaceImpl *surf2;
3157 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3158 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3159 TRACE(" checking surface %p :", surf2);
3160 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3161 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3162 /* Override the Lock / Unlock function for all these surfaces */
3163 surf2->lock_update_prev = surf2->lock_update;
3164 surf2->lock_update = d3ddevice_lock_update;
3165 surf2->unlock_update_prev = surf2->unlock_update;
3166 surf2->unlock_update = d3ddevice_unlock_update;
3167 /* And install also the blt / bltfast overrides */
3168 surf2->aux_blt = d3ddevice_blt;
3169 surf2->aux_bltfast = d3ddevice_bltfast;
3171 TRACE(" overiding direct surface access.\n");
3173 TRACE(" no overide.\n");
3175 surf2->d3ddevice = object;
3179 /* Set the various light parameters */
3180 for (light = 0; light < MAX_LIGHTS; light++) {
3181 /* Only set the fields that are not zero-created */
3182 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3183 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3184 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3185 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3186 object->light_parameters[light].dvDirection.u3.z = 1.0;
3189 /* Allocate memory for the matrices */
3190 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3191 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3192 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3193 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3194 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3195 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3196 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3197 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3198 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3201 /* Initialisation */
3202 TRACE(" setting current context\n");
3203 object->set_context(object);
3204 TRACE(" current context set\n");
3206 /* allocate the clipping planes */
3207 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3208 if (max_clipping_planes>32) {
3209 object->max_clipping_planes=32;
3211 object->max_clipping_planes = max_clipping_planes;
3213 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3214 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3216 glHint(GL_FOG_HINT,GL_NICEST);
3218 glClearColor(0.0, 0.0, 0.0, 0.0);
3219 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3220 glDrawBuffer(buffer);
3221 glReadBuffer(buffer);
3222 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3225 gl_object->state = SURFACE_GL;
3227 /* fill_device_capabilities(d3d->ddraw); */
3229 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3230 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3231 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3232 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3236 TRACE(" creating implementation at %p.\n", *obj);
3238 /* And finally warn D3D that this device is now present */
3239 object->d3d->d3d_added_device(object->d3d, object);
3241 /* FIXME: Should handle other versions than just 7 */
3242 InitDefaultStateBlock(&object->state_block, 7);
3243 /* Apply default render state and texture stage state values */
3244 apply_render_state(object, &object->state_block);
3245 apply_texture_state(object);
3247 /* And fill the fog table with the default fog value */
3248 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);