Fix texture parameters handling on texture change.
[wine/multimedia.git] / dlls / ddraw / d3ddevice / mesa.c
blobae8f55086c3f28a688166a24fd4cdde53745a3ec
1 /* Direct3D Device
2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
5 * Wine supports.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
24 #include <string.h>
25 #include <math.h>
27 #define NONAMELESSUNION
28 #define NONAMELESSSTRUCT
29 #include "windef.h"
30 #include "winerror.h"
31 #include "objbase.h"
32 #include "ddraw.h"
33 #include "d3d.h"
34 #include "wine/debug.h"
36 #include "mesa_private.h"
37 #include "main.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 = {
53 0x31416d44,
54 0x86ae,
55 0x11d2,
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,
63 const GLvoid *table);
64 #endif
66 const float id_mat[16] = {
67 1.0, 0.0, 0.0, 0.0,
68 0.0, 1.0, 0.0, 0.0,
69 0.0, 0.0, 1.0, 0.0,
70 0.0, 0.0, 0.0, 1.0
73 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
74 D3DPRIMITIVETYPE d3dptPrimitiveType,
75 DWORD d3dvtVertexType,
76 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
77 DWORD dwVertexCount,
78 LPWORD dwIndices,
79 DWORD dwIndexCount,
80 DWORD dwFlags) ;
82 /* retrieve the X display to use on a given DC */
83 inline static Display *get_display( HDC hdc )
85 Display *display;
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;
91 return display;
95 /* retrieve the X drawable to use on a given DC */
96 inline static Drawable get_drawable( HDC hdc )
98 Drawable drawable;
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;
104 return drawable;
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);
114 ENTER_GL();
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);
121 LEAVE_GL();
123 return TRUE;
127 /*******************************************************************************
128 * OpenGL static functions
130 static void set_context(IDirect3DDeviceImpl* This)
132 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
134 ENTER_GL();
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);
140 LEAVE_GL();
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)
225 D3DDEVICEDESC d1;
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;
260 d->dwReserved1 = 0;
261 d->dwReserved2 = 0;
262 d->dwReserved3 = 0;
263 d->dwReserved4 = 0;
266 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
267 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
269 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
270 const char *ext_string;
271 Mesa_DeviceCapabilities *devcap;
273 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
274 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
276 ENTER_GL();
277 ext_string = glGetString(GL_EXTENSIONS);
278 /* Query for the ColorTable Extension */
279 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
280 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
281 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
282 } else {
283 TRACE("Color table extension not found.\n");
285 LEAVE_GL();
287 #endif
291 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
293 D3DDEVICEDESC dref, d1, d2;
294 HRESULT ret_value;
296 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
297 Let's put the string in a sufficiently sized array in writable memory. */
298 char device_name[50];
299 strcpy(device_name,"direct3d");
301 fill_opengl_caps(&dref);
303 if (version > 1) {
304 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
305 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
306 d1 = dref;
307 d2 = dref;
308 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
309 if (ret_value != D3DENUMRET_OK)
310 return ret_value;
313 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
314 d1 = dref;
315 d2 = dref;
316 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
317 if (ret_value != D3DENUMRET_OK)
318 return ret_value;
320 return D3DENUMRET_OK;
323 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
325 D3DDEVICEDESC7 ddesc;
327 fill_opengl_caps_7(&ddesc);
329 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
331 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
334 ULONG WINAPI
335 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
337 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
338 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
340 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
341 if (!--(This->ref)) {
342 int i;
343 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
345 /* Release texture associated with the device */
346 for (i = 0; i < MAX_TEXTURES; i++) {
347 if (This->current_texture[i] != NULL)
348 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
349 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
352 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
353 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
354 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
355 surf->aux_ctx = NULL;
356 surf->aux_data = NULL;
357 surf->aux_flip = NULL;
358 break;
361 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
362 IDirectDrawSurfaceImpl *surf2;
363 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
364 for (; surf2 != NULL; surf2 = surf2->next_attached) {
365 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
366 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
367 /* Override the Lock / Unlock function for all these surfaces */
368 surf2->lock_update = surf2->lock_update_prev;
369 surf2->unlock_update = surf2->unlock_update_prev;
370 /* And install also the blt / bltfast overrides */
371 surf2->aux_blt = NULL;
372 surf2->aux_bltfast = NULL;
374 surf2->d3ddevice = NULL;
378 /* And warn the D3D object that this device is no longer active... */
379 This->d3d->removed_device(This->d3d, This);
381 HeapFree(GetProcessHeap(), 0, This->world_mat);
382 HeapFree(GetProcessHeap(), 0, This->view_mat);
383 HeapFree(GetProcessHeap(), 0, This->proj_mat);
385 DeleteCriticalSection(&(This->crit));
387 ENTER_GL();
388 if (glThis->unlock_tex)
389 glDeleteTextures(1, &(glThis->unlock_tex));
390 glXDestroyContext(glThis->display, glThis->gl_context);
391 LEAVE_GL();
392 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
394 HeapFree(GetProcessHeap(), 0, This);
395 return 0;
397 return This->ref;
400 HRESULT WINAPI
401 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
402 LPD3DDEVICEDESC lpD3DHWDevDesc,
403 LPD3DDEVICEDESC lpD3DHELDevDesc)
405 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
406 D3DDEVICEDESC desc;
407 DWORD dwSize;
409 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
411 fill_opengl_caps(&desc);
412 dwSize = lpD3DHWDevDesc->dwSize;
413 memset(lpD3DHWDevDesc, 0, dwSize);
414 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
416 dwSize = lpD3DHELDevDesc->dwSize;
417 memset(lpD3DHELDevDesc, 0, dwSize);
418 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
420 TRACE(" returning caps : (no dump function yet)\n");
422 return DD_OK;
425 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
426 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
427 LPVOID context)
429 DDSURFACEDESC sdesc;
430 LPDDPIXELFORMAT pformat;
432 /* Do the texture enumeration */
433 sdesc.dwSize = sizeof(DDSURFACEDESC);
434 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
435 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
436 pformat = &(sdesc.ddpfPixelFormat);
437 pformat->dwSize = sizeof(DDPIXELFORMAT);
438 pformat->dwFourCC = 0;
440 #if 0
441 /* See argument about the RGBA format for 'packed' texture formats */
442 TRACE("Enumerating GL_RGBA unpacked (32)\n");
443 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
444 pformat->u1.dwRGBBitCount = 32;
445 pformat->u2.dwRBitMask = 0xFF000000;
446 pformat->u3.dwGBitMask = 0x00FF0000;
447 pformat->u4.dwBBitMask = 0x0000FF00;
448 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
449 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
450 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
451 #endif
453 TRACE("Enumerating GL_RGBA unpacked (32)\n");
454 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
455 pformat->u1.dwRGBBitCount = 32;
456 pformat->u2.dwRBitMask = 0x00FF0000;
457 pformat->u3.dwGBitMask = 0x0000FF00;
458 pformat->u4.dwBBitMask = 0x000000FF;
459 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
460 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
461 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
463 #if 0 /* Enabling this breaks Tomb Raider 3, need to investigate... */
464 TRACE("Enumerating GL_RGB unpacked (32)\n");
465 pformat->dwFlags = DDPF_RGB;
466 pformat->u1.dwRGBBitCount = 32;
467 pformat->u2.dwRBitMask = 0x00FF0000;
468 pformat->u3.dwGBitMask = 0x0000FF00;
469 pformat->u4.dwBBitMask = 0x000000FF;
470 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
471 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
472 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
473 #endif
475 TRACE("Enumerating GL_RGB unpacked (24)\n");
476 pformat->dwFlags = DDPF_RGB;
477 pformat->u1.dwRGBBitCount = 24;
478 pformat->u2.dwRBitMask = 0x00FF0000;
479 pformat->u3.dwGBitMask = 0x0000FF00;
480 pformat->u4.dwBBitMask = 0x000000FF;
481 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
482 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
483 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
485 /* Note : even if this is an 'emulated' texture format, it needs to be first
486 as some dumb applications seem to rely on that. */
487 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
488 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
489 pformat->u1.dwRGBBitCount = 16;
490 pformat->u2.dwRBitMask = 0x00007C00;
491 pformat->u3.dwGBitMask = 0x000003E0;
492 pformat->u4.dwBBitMask = 0x0000001F;
493 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
494 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
495 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
497 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
498 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
499 pformat->u1.dwRGBBitCount = 16;
500 pformat->u2.dwRBitMask = 0x00000F00;
501 pformat->u3.dwGBitMask = 0x000000F0;
502 pformat->u4.dwBBitMask = 0x0000000F;
503 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
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_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
508 pformat->dwFlags = DDPF_RGB;
509 pformat->u1.dwRGBBitCount = 16;
510 pformat->u2.dwRBitMask = 0x0000F800;
511 pformat->u3.dwGBitMask = 0x000007E0;
512 pformat->u4.dwBBitMask = 0x0000001F;
513 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
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_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
518 pformat->dwFlags = DDPF_RGB;
519 pformat->u1.dwRGBBitCount = 16;
520 pformat->u2.dwRBitMask = 0x00007C00;
521 pformat->u3.dwGBitMask = 0x000003E0;
522 pformat->u4.dwBBitMask = 0x0000001F;
523 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
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;
527 #if 0
528 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
529 find enumerated, others the last one. And both want to have the ARGB one.
531 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
533 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
534 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
535 pformat->u1.dwRGBBitCount = 16;
536 pformat->u2.dwRBitMask = 0x0000F000;
537 pformat->u3.dwGBitMask = 0x00000F00;
538 pformat->u4.dwBBitMask = 0x000000F0;
539 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
540 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
541 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
543 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
544 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
545 pformat->u1.dwRGBBitCount = 16;
546 pformat->u2.dwRBitMask = 0x0000F800;
547 pformat->u3.dwGBitMask = 0x000007C0;
548 pformat->u4.dwBBitMask = 0x0000003E;
549 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
550 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
551 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
552 #endif
554 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
555 pformat->dwFlags = DDPF_RGB;
556 pformat->u1.dwRGBBitCount = 8;
557 pformat->u2.dwRBitMask = 0x000000E0;
558 pformat->u3.dwGBitMask = 0x0000001C;
559 pformat->u4.dwBBitMask = 0x00000003;
560 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
561 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
562 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
564 TRACE("Enumerating Paletted (8)\n");
565 pformat->dwFlags = DDPF_PALETTEINDEXED8;
566 pformat->u1.dwRGBBitCount = 8;
567 pformat->u2.dwRBitMask = 0x00000000;
568 pformat->u3.dwGBitMask = 0x00000000;
569 pformat->u4.dwBBitMask = 0x00000000;
570 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
571 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
572 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
574 TRACE("End of enumeration\n");
575 return DD_OK;
579 HRESULT
580 d3ddevice_find(IDirect3DImpl *d3d,
581 LPD3DFINDDEVICESEARCH lpD3DDFS,
582 LPD3DFINDDEVICERESULT lplpD3DDevice)
584 D3DDEVICEDESC desc;
586 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
587 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
588 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
589 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
591 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
592 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
593 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
594 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
595 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
596 TRACE(" no match for this GUID.\n");
597 return DDERR_INVALIDPARAMS;
601 /* Now return our own GUID */
602 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
603 fill_opengl_caps(&desc);
604 lplpD3DDevice->ddHwDesc = desc;
605 lplpD3DDevice->ddSwDesc = desc;
607 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
609 return D3D_OK;
612 HRESULT WINAPI
613 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
614 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
615 LPVOID lpArg)
617 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
618 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
619 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
622 HRESULT WINAPI
623 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
624 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
625 LPVOID lpArg)
627 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
628 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
629 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
632 HRESULT WINAPI
633 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
634 D3DRENDERSTATETYPE dwRenderStateType,
635 DWORD dwRenderState)
637 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
638 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
640 /* Call the render state functions */
641 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
642 set_render_state(This, dwRenderStateType, &This->state_block);
644 return DD_OK;
647 HRESULT WINAPI
648 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
649 D3DRENDERSTATETYPE dwRenderStateType,
650 LPDWORD lpdwRenderState)
652 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
653 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
655 /* Call the render state functions */
656 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
658 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
660 return DD_OK;
663 HRESULT WINAPI
664 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
665 D3DLIGHTSTATETYPE dwLightStateType,
666 DWORD dwLightState)
668 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
670 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
672 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
673 TRACE("Unexpected Light State Type\n");
674 return DDERR_INVALIDPARAMS;
676 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
677 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
679 if (mat != NULL) {
680 ENTER_GL();
681 mat->activate(mat);
682 LEAVE_GL();
683 } else {
684 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
686 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
687 switch (dwLightState) {
688 case D3DCOLOR_MONO:
689 ERR("DDCOLOR_MONO should not happen!\n");
690 break;
691 case D3DCOLOR_RGB:
692 /* We are already in this mode */
693 break;
694 default:
695 ERR("Unknown color model!\n");
696 break;
698 } else {
699 D3DRENDERSTATETYPE rs;
700 switch (dwLightStateType) {
702 case D3DLIGHTSTATE_AMBIENT: /* 2 */
703 rs = D3DRENDERSTATE_AMBIENT;
704 break;
705 case D3DLIGHTSTATE_FOGMODE: /* 4 */
706 rs = D3DRENDERSTATE_FOGVERTEXMODE;
707 break;
708 case D3DLIGHTSTATE_FOGSTART: /* 5 */
709 rs = D3DRENDERSTATE_FOGSTART;
710 break;
711 case D3DLIGHTSTATE_FOGEND: /* 6 */
712 rs = D3DRENDERSTATE_FOGEND;
713 break;
714 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
715 rs = D3DRENDERSTATE_FOGDENSITY;
716 break;
717 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
718 rs = D3DRENDERSTATE_COLORVERTEX;
719 break;
720 default:
721 break;
724 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
725 rs,dwLightState);
728 return DD_OK;
731 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
733 switch (d3dpt) {
734 case D3DPT_POINTLIST:
735 TRACE("Start POINTS\n");
736 glBegin(GL_POINTS);
737 break;
739 case D3DPT_LINELIST:
740 TRACE("Start LINES\n");
741 glBegin(GL_LINES);
742 break;
744 case D3DPT_LINESTRIP:
745 TRACE("Start LINE_STRIP\n");
746 glBegin(GL_LINE_STRIP);
747 break;
749 case D3DPT_TRIANGLELIST:
750 TRACE("Start TRIANGLES\n");
751 glBegin(GL_TRIANGLES);
752 break;
754 case D3DPT_TRIANGLESTRIP:
755 TRACE("Start TRIANGLE_STRIP\n");
756 glBegin(GL_TRIANGLE_STRIP);
757 break;
759 case D3DPT_TRIANGLEFAN:
760 TRACE("Start TRIANGLE_FAN\n");
761 glBegin(GL_TRIANGLE_FAN);
762 break;
764 default:
765 FIXME("Unhandled primitive %08x\n", d3dpt);
766 break;
770 /* This function calculate the Z coordinate from Zproj */
771 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
773 float a,b,c,d;
774 /* Assume that X = Y = 0 and W = 1 */
775 a = This->proj_mat->_33;
776 b = This->proj_mat->_34;
777 c = This->proj_mat->_43;
778 d = This->proj_mat->_44;
779 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
780 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
781 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
783 return (d*Zproj - c) / (a - b*Zproj);
786 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
787 int i;
789 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
791 for (i = 0; i < 3; i++) {
792 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
793 DWORD elt;
794 for (elt = 0; elt < 0x10000; elt++) {
795 /* We apply the fog transformation and cache the result */
796 DWORD fog_intensity = elt & 0xFF;
797 DWORD vertex_color = (elt >> 8) & 0xFF;
798 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
803 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
804 BOOLEAN vertex_transformed,
805 BOOLEAN vertex_lit) {
806 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
808 /* Puts GL in the correct lighting / transformation mode */
809 if ((vertex_transformed == FALSE) &&
810 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
811 /* Need to put the correct transformation again if we go from Transformed
812 vertices to non-transformed ones.
814 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
815 This->world_mat, This->view_mat, This->proj_mat);
816 glThis->transform_state = GL_TRANSFORM_NORMAL;
818 } else if ((vertex_transformed == TRUE) &&
819 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
820 /* Set our orthographic projection */
821 glThis->transform_state = GL_TRANSFORM_ORTHO;
822 d3ddevice_set_ortho(This);
825 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
826 if no fogging state change occured */
827 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
828 if (vertex_transformed == TRUE) {
829 glDisable(GL_FOG);
830 /* Now check if our fog_table still corresponds to the current vertex color.
831 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
832 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
833 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
834 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
835 /* We need to rebuild our fog table.... */
836 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
838 } else {
839 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
840 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
841 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
842 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
843 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
845 if (vertex_lit == FALSE) {
846 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
847 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
848 } else {
849 /* Special case of 'pixel fog' */
850 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
851 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
853 glEnable(GL_FOG);
854 } else {
855 glDisable(GL_FOG);
858 } else {
859 glDisable(GL_FOG);
862 /* Handle the 'no-normal' case */
863 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
864 glEnable(GL_LIGHTING);
865 else
866 glDisable(GL_LIGHTING);
868 /* Handle the code for pre-vertex material properties */
869 if (vertex_transformed == FALSE) {
870 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
871 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
872 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
873 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
874 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
875 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
876 glEnable(GL_COLOR_MATERIAL);
883 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
884 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
886 D3DDRAWPRIMITIVESTRIDEDDATA strided;
888 switch (d3dvt) {
889 case D3DVT_VERTEX: {
890 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
891 strided.position.dwStride = sizeof(D3DVERTEX);
892 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
893 strided.normal.dwStride = sizeof(D3DVERTEX);
894 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
895 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
896 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
897 } break;
899 case D3DVT_LVERTEX: {
900 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
901 strided.position.dwStride = sizeof(D3DLVERTEX);
902 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
903 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
904 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
905 strided.specular.dwStride = sizeof(D3DLVERTEX);
906 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
907 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
908 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
909 } break;
911 case D3DVT_TLVERTEX: {
912 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
913 strided.position.dwStride = sizeof(D3DTLVERTEX);
914 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
915 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
916 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
917 strided.specular.dwStride = sizeof(D3DTLVERTEX);
918 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
919 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
920 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
921 } break;
923 default:
924 FIXME("Unhandled vertex type %08x\n", d3dvt);
925 break;
929 HRESULT WINAPI
930 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
931 D3DPRIMITIVETYPE d3dptPrimitiveType,
932 D3DVERTEXTYPE d3dvtVertexType,
933 LPVOID lpvVertices,
934 DWORD dwVertexCount,
935 DWORD dwFlags)
937 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
939 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
940 if (TRACE_ON(ddraw)) {
941 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
944 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
946 return DD_OK;
949 HRESULT WINAPI
950 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
951 D3DPRIMITIVETYPE d3dptPrimitiveType,
952 D3DVERTEXTYPE d3dvtVertexType,
953 LPVOID lpvVertices,
954 DWORD dwVertexCount,
955 LPWORD dwIndices,
956 DWORD dwIndexCount,
957 DWORD dwFlags)
959 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
960 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
961 if (TRACE_ON(ddraw)) {
962 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
965 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
967 return DD_OK;
970 HRESULT WINAPI
971 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
972 LPD3DEXECUTEBUFFERDESC lpDesc,
973 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
974 IUnknown* pUnkOuter)
976 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
977 IDirect3DExecuteBufferImpl *ret;
978 HRESULT ret_value;
980 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
982 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
983 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
985 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
987 return ret_value;
990 /* These are the various handler used in the generic path */
991 inline static void handle_xyz(D3DVALUE *coords) {
992 glVertex3fv(coords);
994 inline static void handle_xyzrhw(D3DVALUE *coords) {
995 if (coords[3] < 1e-8)
996 glVertex3fv(coords);
997 else {
998 GLfloat w = 1.0 / coords[3];
1000 glVertex4f(coords[0] * w,
1001 coords[1] * w,
1002 coords[2] * w,
1006 inline static void handle_normal(D3DVALUE *coords) {
1007 glNormal3fv(coords);
1010 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1011 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1012 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1013 glColor4ub((*color >> 16) & 0xFF,
1014 (*color >> 8) & 0xFF,
1015 (*color >> 0) & 0xFF,
1016 (*color >> 24) & 0xFF);
1017 } else {
1018 glColor3ub((*color >> 16) & 0xFF,
1019 (*color >> 8) & 0xFF,
1020 (*color >> 0) & 0xFF);
1024 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1025 glColor4ub((*color >> 16) & 0xFF,
1026 (*color >> 8) & 0xFF,
1027 (*color >> 0) & 0xFF,
1028 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1031 inline static void handle_diffuse(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_COLOR1) {
1036 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1037 handle_diffuse_base(sb, color);
1039 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1040 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1041 handle_diffuse_base(sb, color);
1043 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1044 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1045 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1046 handle_diffuse_base(sb, color);
1048 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1049 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1050 handle_diffuse_base(sb, color);
1052 } else {
1053 handle_diffuse_base(sb, color);
1057 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1058 if ((lighted == FALSE) &&
1059 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1060 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1061 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1062 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1063 handle_specular_base(sb, color);
1065 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1066 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1067 handle_specular_base(sb, color);
1069 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1070 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1071 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1072 handle_specular_base(sb, color);
1074 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1075 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1076 handle_specular_base(sb, color);
1079 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1082 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1083 if (lighted == TRUE) {
1084 DWORD color = *color_d;
1085 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1086 /* Special case where the specular value is used to do fogging */
1087 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1088 color &= 0xFF000000; /* Only keep the alpha component */
1089 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1090 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1091 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1093 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1094 /* Standard specular value in transformed mode. TODO */
1096 handle_diffuse_base(sb, &color);
1097 } else {
1098 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1099 handle_diffuse(sb, color_d, FALSE);
1100 handle_specular(sb, color_s, FALSE);
1101 } else {
1102 /* In that case, only put the diffuse color... */
1103 handle_diffuse_base(sb, color_d);
1108 inline static void handle_texture(D3DVALUE *coords) {
1109 glTexCoord2fv(coords);
1111 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
1112 /* For the moment, draw only the first texture.. */
1113 if (tex_index == 0) glTexCoord2fv(coords);
1116 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1117 D3DPRIMITIVETYPE d3dptPrimitiveType,
1118 DWORD d3dvtVertexType,
1119 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1120 DWORD dwVertexCount,
1121 LPWORD dwIndices,
1122 DWORD dwIndexCount,
1123 DWORD dwFlags)
1125 BOOLEAN vertex_lighted = FALSE;
1126 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1127 int num_active_stages = 0;
1129 /* This is to prevent 'thread contention' between a thread locking the device and another
1130 doing 3D display on it... */
1131 EnterCriticalSection(&(This->crit));
1133 ENTER_GL();
1134 if (glThis->state == SURFACE_MEMORY_DIRTY) {
1135 This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
1138 glThis->state = SURFACE_GL;
1140 /* Compute the number of active texture stages */
1141 while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
1143 if (TRACE_ON(ddraw)) {
1144 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1147 /* Just a hack for now.. Will have to find better algorithm :-/ */
1148 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1149 vertex_lighted = TRUE;
1150 } else {
1151 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1154 draw_primitive_handle_GL_state(This,
1155 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1156 vertex_lighted);
1157 draw_primitive_start_GL(d3dptPrimitiveType);
1159 /* Some fast paths first before the generic case.... */
1160 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1161 int index;
1163 for (index = 0; index < dwIndexCount; index++) {
1164 int i = (dwIndices == NULL) ? index : dwIndices[index];
1165 D3DVALUE *normal =
1166 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1167 D3DVALUE *tex_coord =
1168 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1169 D3DVALUE *position =
1170 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1172 handle_normal(normal);
1173 handle_texture(tex_coord);
1174 handle_xyz(position);
1176 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1177 position[0], position[1], position[2],
1178 normal[0], normal[1], normal[2],
1179 tex_coord[0], tex_coord[1]);
1181 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1182 int index;
1184 for (index = 0; index < dwIndexCount; index++) {
1185 int i = (dwIndices == NULL) ? index : dwIndices[index];
1186 DWORD *color_d =
1187 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1188 DWORD *color_s =
1189 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1190 D3DVALUE *tex_coord =
1191 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1192 D3DVALUE *position =
1193 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1195 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1196 handle_texture(tex_coord);
1197 handle_xyzrhw(position);
1199 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1200 position[0], position[1], position[2], position[3],
1201 (*color_d >> 16) & 0xFF,
1202 (*color_d >> 8) & 0xFF,
1203 (*color_d >> 0) & 0xFF,
1204 (*color_d >> 24) & 0xFF,
1205 (*color_s >> 16) & 0xFF,
1206 (*color_s >> 8) & 0xFF,
1207 (*color_s >> 0) & 0xFF,
1208 (*color_s >> 24) & 0xFF,
1209 tex_coord[0], tex_coord[1]);
1211 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1212 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1213 /* This is the 'slow path' but that should support all possible vertex formats out there...
1214 Note that people should write a fast path for all vertex formats out there...
1216 int index;
1217 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1218 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1220 for (index = 0; index < dwIndexCount; index++) {
1221 int i = (dwIndices == NULL) ? index : dwIndices[index];
1222 int tex_stage;
1224 if (d3dvtVertexType & D3DFVF_NORMAL) {
1225 D3DVALUE *normal =
1226 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1227 handle_normal(normal);
1229 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1230 DWORD *color_d =
1231 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1232 DWORD *color_s =
1233 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1234 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1235 } else {
1236 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1237 DWORD *color_s =
1238 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1239 handle_specular(&(This->state_block), color_s, vertex_lighted);
1240 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1241 DWORD *color_d =
1242 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1243 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1247 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1248 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0xFFFF000;
1249 if (tex_index >= num_tex_index) {
1250 handle_textures((D3DVALUE *) no_index, tex_stage);
1251 } else {
1252 D3DVALUE *tex_coord =
1253 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1254 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1255 handle_textures(tex_coord, tex_stage);
1259 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1260 D3DVALUE *position =
1261 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1262 handle_xyz(position);
1263 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1264 D3DVALUE *position =
1265 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1266 handle_xyzrhw(position);
1269 if (TRACE_ON(ddraw_geom)) {
1270 int tex_index;
1272 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1273 D3DVALUE *position =
1274 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1275 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1276 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1277 D3DVALUE *position =
1278 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1279 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1281 if (d3dvtVertexType & D3DFVF_NORMAL) {
1282 D3DVALUE *normal =
1283 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1284 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1286 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1287 DWORD *color_d =
1288 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1289 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1290 (*color_d >> 16) & 0xFF,
1291 (*color_d >> 8) & 0xFF,
1292 (*color_d >> 0) & 0xFF,
1293 (*color_d >> 24) & 0xFF);
1295 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1296 DWORD *color_s =
1297 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1298 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1299 (*color_s >> 16) & 0xFF,
1300 (*color_s >> 8) & 0xFF,
1301 (*color_s >> 0) & 0xFF,
1302 (*color_s >> 24) & 0xFF);
1304 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1305 D3DVALUE *tex_coord =
1306 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1307 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1308 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1310 TRACE_(ddraw_geom)("\n");
1313 } else {
1314 ERR(" matrix weighting not handled yet....\n");
1317 glEnd();
1319 /* Whatever the case, disable the color material stuff */
1320 glDisable(GL_COLOR_MATERIAL);
1322 LEAVE_GL();
1323 TRACE("End\n");
1325 LeaveCriticalSection(&(This->crit));
1328 HRESULT WINAPI
1329 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1330 D3DPRIMITIVETYPE d3dptPrimitiveType,
1331 DWORD d3dvtVertexType,
1332 LPVOID lpvVertices,
1333 DWORD dwVertexCount,
1334 DWORD dwFlags)
1336 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1337 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1339 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1340 if (TRACE_ON(ddraw)) {
1341 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1344 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1345 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1347 return DD_OK;
1350 HRESULT WINAPI
1351 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1352 D3DPRIMITIVETYPE d3dptPrimitiveType,
1353 DWORD d3dvtVertexType,
1354 LPVOID lpvVertices,
1355 DWORD dwVertexCount,
1356 LPWORD dwIndices,
1357 DWORD dwIndexCount,
1358 DWORD dwFlags)
1360 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1361 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1363 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1364 if (TRACE_ON(ddraw)) {
1365 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1368 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1369 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1371 return DD_OK;
1374 HRESULT WINAPI
1375 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1376 D3DPRIMITIVETYPE d3dptPrimitiveType,
1377 DWORD dwVertexType,
1378 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1379 DWORD dwVertexCount,
1380 DWORD dwFlags)
1382 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1384 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1385 if (TRACE_ON(ddraw)) {
1386 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1388 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1390 return DD_OK;
1393 HRESULT WINAPI
1394 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1395 D3DPRIMITIVETYPE d3dptPrimitiveType,
1396 DWORD dwVertexType,
1397 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1398 DWORD dwVertexCount,
1399 LPWORD lpIndex,
1400 DWORD dwIndexCount,
1401 DWORD dwFlags)
1403 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1405 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1406 if (TRACE_ON(ddraw)) {
1407 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1410 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1412 return DD_OK;
1415 HRESULT WINAPI
1416 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1417 D3DPRIMITIVETYPE d3dptPrimitiveType,
1418 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1419 DWORD dwStartVertex,
1420 DWORD dwNumVertices,
1421 DWORD dwFlags)
1423 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1424 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1425 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1427 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1428 if (TRACE_ON(ddraw)) {
1429 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1432 if (vb_impl->processed == TRUE) {
1433 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1434 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1436 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1437 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1438 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1440 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1441 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1443 } else {
1444 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1445 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1448 return DD_OK;
1451 HRESULT WINAPI
1452 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1453 D3DPRIMITIVETYPE d3dptPrimitiveType,
1454 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1455 DWORD dwStartVertex,
1456 DWORD dwNumVertices,
1457 LPWORD lpwIndices,
1458 DWORD dwIndexCount,
1459 DWORD dwFlags)
1461 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1462 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1463 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1465 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1466 if (TRACE_ON(ddraw)) {
1467 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1470 if (vb_impl->processed == TRUE) {
1471 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1472 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1474 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1475 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1476 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1478 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1479 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1481 } else {
1482 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1483 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1486 return DD_OK;
1489 static GLenum
1490 convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
1492 GLenum gl_state;
1494 if (dwMipState == D3DTFP_NONE) {
1495 switch (dwMinState) {
1496 case D3DTFN_POINT: gl_state = GL_NEAREST; break;
1497 case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
1498 default: gl_state = GL_LINEAR; break;
1500 } else if (dwMipState == D3DTFP_POINT) {
1501 switch (dwMinState) {
1502 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
1503 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1504 default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
1506 } else {
1507 switch (dwMinState) {
1508 case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
1509 case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1510 default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
1513 return gl_state;
1516 static GLenum
1517 convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
1519 GLenum gl_state;
1521 switch (dwState) {
1522 case D3DTFG_POINT:
1523 gl_state = GL_NEAREST;
1524 break;
1525 case D3DTFG_LINEAR:
1526 gl_state = GL_LINEAR;
1527 break;
1528 default:
1529 gl_state = GL_LINEAR;
1530 break;
1532 return gl_state;
1535 static GLenum
1536 convert_tex_address_to_GL(D3DTEXTUREADDRESS dwState)
1538 GLenum gl_state;
1539 switch (dwState) {
1540 case D3DTADDRESS_WRAP: gl_state = GL_REPEAT; break;
1541 case D3DTADDRESS_CLAMP: gl_state = GL_CLAMP; break;
1542 case D3DTADDRESS_BORDER: gl_state = GL_CLAMP_TO_EDGE; break;
1543 #if defined(GL_VERSION_1_4)
1544 case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT; break;
1545 #elif defined(GL_ARB_texture_mirrored_repeat)
1546 case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT_ARB; break;
1547 #endif
1548 default: gl_state = GL_REPEAT; break;
1550 return gl_state;
1553 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1554 static BOOLEAN
1555 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1557 BOOLEAN is_complement = FALSE;
1558 BOOLEAN is_alpha_replicate = FALSE;
1559 BOOLEAN handled = TRUE;
1560 GLenum src;
1561 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1562 int num;
1564 if (is_color) {
1565 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1566 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1567 else {
1568 handled = FALSE;
1569 num = 0;
1571 if (tex_op == D3DTOP_SELECTARG2) {
1572 num = 1 - num;
1574 } else {
1575 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1576 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1577 else {
1578 handled = FALSE;
1579 num = 0;
1581 if (tex_op == D3DTOP_SELECTARG2) {
1582 num = 1 - num;
1586 if (dwState & D3DTA_COMPLEMENT) {
1587 is_complement = TRUE;
1589 if (dwState & D3DTA_ALPHAREPLICATE) {
1590 is_alpha_replicate = TRUE;
1592 dwState &= D3DTA_SELECTMASK;
1593 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1594 dwState = D3DTA_DIFFUSE;
1597 switch (dwState) {
1598 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1599 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1600 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1601 case D3DTA_TFACTOR: {
1602 /* Get the constant value from the current rendering state */
1603 GLfloat color[4];
1604 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1606 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1607 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1608 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1609 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1610 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1612 src = GL_CONSTANT_EXT;
1613 } break;
1614 default: src = GL_TEXTURE; handled = FALSE; break;
1617 if (is_color) {
1618 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1619 if (is_alpha_replicate) {
1620 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1621 } else {
1622 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1624 } else {
1625 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1626 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1629 return handled;
1632 HRESULT WINAPI
1633 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1634 DWORD dwStage,
1635 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1636 DWORD dwState)
1638 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1639 const char *type;
1640 DWORD prev_state;
1642 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1644 if (dwStage > 0) return DD_OK; /* We nothing in this case for now */
1646 switch (d3dTexStageStateType) {
1647 #define GEN_CASE(a) case a: type = #a; break
1648 GEN_CASE(D3DTSS_COLOROP);
1649 GEN_CASE(D3DTSS_COLORARG1);
1650 GEN_CASE(D3DTSS_COLORARG2);
1651 GEN_CASE(D3DTSS_ALPHAOP);
1652 GEN_CASE(D3DTSS_ALPHAARG1);
1653 GEN_CASE(D3DTSS_ALPHAARG2);
1654 GEN_CASE(D3DTSS_BUMPENVMAT00);
1655 GEN_CASE(D3DTSS_BUMPENVMAT01);
1656 GEN_CASE(D3DTSS_BUMPENVMAT10);
1657 GEN_CASE(D3DTSS_BUMPENVMAT11);
1658 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1659 GEN_CASE(D3DTSS_ADDRESS);
1660 GEN_CASE(D3DTSS_ADDRESSU);
1661 GEN_CASE(D3DTSS_ADDRESSV);
1662 GEN_CASE(D3DTSS_BORDERCOLOR);
1663 GEN_CASE(D3DTSS_MAGFILTER);
1664 GEN_CASE(D3DTSS_MINFILTER);
1665 GEN_CASE(D3DTSS_MIPFILTER);
1666 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1667 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1668 GEN_CASE(D3DTSS_MAXANISOTROPY);
1669 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1670 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1671 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1672 #undef GEN_CASE
1673 default: type = "UNKNOWN";
1676 /* Store the values in the state array */
1677 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1678 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1679 /* Some special cases when one state modifies more than one... */
1680 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1681 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1682 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1685 ENTER_GL();
1687 switch (d3dTexStageStateType) {
1688 case D3DTSS_MINFILTER:
1689 case D3DTSS_MIPFILTER:
1690 if (TRACE_ON(ddraw)) {
1691 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1692 switch ((D3DTEXTUREMINFILTER) dwState) {
1693 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1694 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1695 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1697 } else {
1698 switch ((D3DTEXTUREMIPFILTER) dwState) {
1699 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1700 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1701 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1702 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1707 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1708 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
1709 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
1710 break;
1712 case D3DTSS_MAGFILTER:
1713 if (TRACE_ON(ddraw)) {
1714 switch ((D3DTEXTUREMAGFILTER) dwState) {
1715 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_POINT\n"); break;
1716 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFN_LINEAR\n"); break;
1717 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1720 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
1721 break;
1723 case D3DTSS_ADDRESS:
1724 case D3DTSS_ADDRESSU:
1725 case D3DTSS_ADDRESSV: {
1726 GLenum arg = convert_tex_address_to_GL(dwState);
1728 switch ((D3DTEXTUREADDRESS) dwState) {
1729 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1730 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1731 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1732 #if defined(GL_VERSION_1_4)
1733 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1734 #elif defined(GL_ARB_texture_mirrored_repeat)
1735 case D3DTADDRESS_MIRROR: TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type); break;
1736 #endif
1737 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1740 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1741 (d3dTexStageStateType == D3DTSS_ADDRESSU))
1742 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
1743 if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
1744 (d3dTexStageStateType == D3DTSS_ADDRESSV))
1745 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
1746 } break;
1748 case D3DTSS_ALPHAOP:
1749 case D3DTSS_COLOROP: {
1750 int scale = 1;
1751 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1752 const char *value;
1753 int handled = 1;
1755 switch (dwState) {
1756 #define GEN_CASE(a) case a: value = #a; break
1757 GEN_CASE(D3DTOP_DISABLE);
1758 GEN_CASE(D3DTOP_SELECTARG1);
1759 GEN_CASE(D3DTOP_SELECTARG2);
1760 GEN_CASE(D3DTOP_MODULATE);
1761 GEN_CASE(D3DTOP_MODULATE2X);
1762 GEN_CASE(D3DTOP_MODULATE4X);
1763 GEN_CASE(D3DTOP_ADD);
1764 GEN_CASE(D3DTOP_ADDSIGNED);
1765 GEN_CASE(D3DTOP_ADDSIGNED2X);
1766 GEN_CASE(D3DTOP_SUBTRACT);
1767 GEN_CASE(D3DTOP_ADDSMOOTH);
1768 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1769 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1770 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1771 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1772 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1773 GEN_CASE(D3DTOP_PREMODULATE);
1774 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1775 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1776 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1777 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1778 GEN_CASE(D3DTOP_BUMPENVMAP);
1779 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1780 GEN_CASE(D3DTOP_DOTPRODUCT3);
1781 GEN_CASE(D3DTOP_FORCE_DWORD);
1782 #undef GEN_CASE
1783 default: value = "UNKNOWN";
1786 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE) && (dwStage == 0)) {
1787 glDisable(GL_TEXTURE_2D);
1788 TRACE(" disabling 2D texturing.\n");
1789 } else {
1790 /* Re-enable texturing */
1791 if ((dwStage == 0) && (This->current_texture[0] != NULL)) {
1792 glEnable(GL_TEXTURE_2D);
1793 TRACE(" enabling 2D texturing.\n");
1796 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1797 if (dwState != D3DTOP_DISABLE) {
1798 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1801 /* Now set up the operand correctly */
1802 switch (dwState) {
1803 case D3DTOP_DISABLE:
1804 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1805 and it works, so ignore this op */
1806 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1807 break;
1809 case D3DTOP_SELECTARG1:
1810 case D3DTOP_SELECTARG2:
1811 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1812 break;
1814 case D3DTOP_MODULATE4X:
1815 scale = scale * 2; /* Drop through */
1816 case D3DTOP_MODULATE2X:
1817 scale = scale * 2; /* Drop through */
1818 case D3DTOP_MODULATE:
1819 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1820 break;
1822 case D3DTOP_ADD:
1823 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1824 break;
1826 case D3DTOP_ADDSIGNED2X:
1827 scale = scale * 2; /* Drop through */
1828 case D3DTOP_ADDSIGNED:
1829 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1830 break;
1832 /* For the four blending modes, use the Arg2 parameter */
1833 case D3DTOP_BLENDDIFFUSEALPHA:
1834 case D3DTOP_BLENDTEXTUREALPHA:
1835 case D3DTOP_BLENDFACTORALPHA:
1836 case D3DTOP_BLENDCURRENTALPHA: {
1837 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1839 switch (dwState) {
1840 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1841 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1842 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1843 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1846 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1847 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1848 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1849 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1850 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1851 } break;
1853 default:
1854 handled = FALSE;
1855 break;
1859 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1860 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1861 /* Switch the arguments if needed... */
1862 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1863 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1864 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1865 dwState);
1866 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1867 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1868 dwState);
1869 } else {
1870 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1871 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1872 dwState);
1873 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1874 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1875 dwState);
1879 if (handled) {
1880 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1881 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1882 } else {
1883 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1885 TRACE(" Stage type is : %s => %s\n", type, value);
1886 } else {
1887 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1889 } break;
1891 case D3DTSS_COLORARG1:
1892 case D3DTSS_COLORARG2:
1893 case D3DTSS_ALPHAARG1:
1894 case D3DTSS_ALPHAARG2: {
1895 const char *value, *value_comp = "", *value_alpha = "";
1896 BOOLEAN handled;
1897 D3DTEXTUREOP tex_op;
1899 switch (dwState & D3DTA_SELECTMASK) {
1900 #define GEN_CASE(a) case a: value = #a; break
1901 GEN_CASE(D3DTA_DIFFUSE);
1902 GEN_CASE(D3DTA_CURRENT);
1903 GEN_CASE(D3DTA_TEXTURE);
1904 GEN_CASE(D3DTA_TFACTOR);
1905 GEN_CASE(D3DTA_SPECULAR);
1906 #undef GEN_CASE
1907 default: value = "UNKNOWN";
1909 if (dwState & D3DTA_COMPLEMENT) {
1910 value_comp = " | D3DTA_COMPLEMENT";
1912 if (dwState & D3DTA_ALPHAREPLICATE) {
1913 value_alpha = " | D3DTA_ALPHAREPLICATE";
1916 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1917 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1918 } else {
1919 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1922 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
1924 if (handled) {
1925 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1926 } else {
1927 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1929 } break;
1931 case D3DTSS_MIPMAPLODBIAS: {
1932 D3DVALUE value = *((D3DVALUE *) &dwState);
1933 BOOLEAN handled = TRUE;
1935 if (value != 0.0)
1936 handled = FALSE;
1938 if (handled) {
1939 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1940 } else {
1941 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1943 } break;
1945 case D3DTSS_MAXMIPLEVEL:
1946 if (dwState == 0) {
1947 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
1948 } else {
1949 FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
1951 break;
1953 case D3DTSS_BORDERCOLOR: {
1954 GLfloat color[4];
1956 color[0] = ((dwState >> 16) & 0xFF) / 255.0;
1957 color[1] = ((dwState >> 8) & 0xFF) / 255.0;
1958 color[2] = ((dwState >> 0) & 0xFF) / 255.0;
1959 color[3] = ((dwState >> 24) & 0xFF) / 255.0;
1961 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
1963 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
1964 ((dwState >> 16) & 0xFF),
1965 ((dwState >> 8) & 0xFF),
1966 ((dwState >> 0) & 0xFF),
1967 ((dwState >> 24) & 0xFF));
1968 } break;
1970 case D3DTSS_TEXCOORDINDEX: {
1971 BOOLEAN handled = TRUE;
1972 const char *value;
1974 switch (dwState & 0xFFFF0000) {
1975 #define GEN_CASE(a) case a: value = #a; break
1976 GEN_CASE(D3DTSS_TCI_PASSTHRU);
1977 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
1978 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
1979 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
1980 #undef GEN_CASE
1981 default: value = "UNKNOWN";
1983 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
1984 handled = FALSE;
1986 if (handled) {
1987 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1988 } else {
1989 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
1991 } break;
1993 case D3DTSS_TEXTURETRANSFORMFLAGS: {
1994 const char *projected = "", *value;
1995 BOOLEAN handled = TRUE;
1996 switch (dwState & 0xFF) {
1997 #define GEN_CASE(a) case a: value = #a; break
1998 GEN_CASE(D3DTTFF_DISABLE);
1999 GEN_CASE(D3DTTFF_COUNT1);
2000 GEN_CASE(D3DTTFF_COUNT2);
2001 GEN_CASE(D3DTTFF_COUNT3);
2002 GEN_CASE(D3DTTFF_COUNT4);
2003 #undef GEN_CASE
2004 default: value = "UNKNOWN";
2006 if (dwState & D3DTTFF_PROJECTED) {
2007 projected = " | D3DTTFF_PROJECTED";
2008 handled = FALSE;
2011 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2012 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2015 if (handled == TRUE) {
2016 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2017 } else {
2018 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2020 } break;
2022 default:
2023 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2024 break;
2027 LEAVE_GL();
2029 return DD_OK;
2032 HRESULT WINAPI
2033 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2034 DWORD dwStage,
2035 LPDIRECTDRAWSURFACE7 lpTexture2)
2037 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2039 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2041 if (dwStage > 0) return DD_OK;
2043 if (This->current_texture[dwStage] != NULL) {
2044 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2047 ENTER_GL();
2048 if (lpTexture2 == NULL) {
2049 This->current_texture[dwStage] = NULL;
2051 TRACE(" disabling 2D texturing.\n");
2052 glBindTexture(GL_TEXTURE_2D, 0);
2053 glDisable(GL_TEXTURE_2D);
2054 } else {
2055 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2056 GLint max_mip_level;
2057 GLfloat color[4];
2059 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
2061 if (This->current_texture[dwStage] == tex_impl) {
2062 /* No need to do anything as the texture did not change. */
2063 return DD_OK;
2065 This->current_texture[dwStage] = tex_impl;
2067 if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2068 /* Do not re-enable texturing if it was disabled due to the COLOROP code */
2069 glEnable(GL_TEXTURE_2D);
2070 TRACE(" enabling 2D texturing.\n");
2072 gltex_upload_texture(tex_impl);
2074 if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
2075 max_mip_level = 0;
2076 } else {
2077 max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
2080 /* Now we need to reset all glTexParameter calls for this particular texture... */
2081 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
2082 convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
2083 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
2084 convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
2085 This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
2086 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
2087 convert_tex_address_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1]));
2088 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
2089 convert_tex_address_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1]));
2090 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
2091 color[0] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 16) & 0xFF) / 255.0;
2092 color[1] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 8) & 0xFF) / 255.0;
2093 color[2] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 0) & 0xFF) / 255.0;
2094 color[3] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 24) & 0xFF) / 255.0;
2095 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
2097 LEAVE_GL();
2099 return DD_OK;
2102 HRESULT WINAPI
2103 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2104 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2106 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2107 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2109 fill_opengl_caps_7(lpD3DHELDevDesc);
2111 TRACE(" returning caps : no dump function yet.\n");
2113 return DD_OK;
2116 HRESULT WINAPI
2117 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2118 LPD3DMATERIAL7 lpMat)
2120 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2121 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2123 if (TRACE_ON(ddraw)) {
2124 TRACE(" material is : \n");
2125 dump_D3DMATERIAL7(lpMat);
2128 This->current_material = *lpMat;
2130 glMaterialfv(GL_FRONT_AND_BACK,
2131 GL_DIFFUSE,
2132 (float *) &(This->current_material.u.diffuse));
2133 glMaterialfv(GL_FRONT_AND_BACK,
2134 GL_AMBIENT,
2135 (float *) &(This->current_material.u1.ambient));
2136 glMaterialfv(GL_FRONT_AND_BACK,
2137 GL_SPECULAR,
2138 (float *) &(This->current_material.u2.specular));
2139 glMaterialfv(GL_FRONT_AND_BACK,
2140 GL_EMISSION,
2141 (float *) &(This->current_material.u3.emissive));
2142 glMaterialf(GL_FRONT_AND_BACK,
2143 GL_SHININESS,
2144 This->current_material.u4.power); /* Not sure about this... */
2146 return DD_OK;
2150 HRESULT WINAPI
2151 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2152 DWORD dwLightIndex,
2153 LPD3DLIGHT7 lpLight)
2155 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2156 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2157 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2159 if (TRACE_ON(ddraw)) {
2160 TRACE(" setting light : \n");
2161 dump_D3DLIGHT7(lpLight);
2164 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2165 This->set_lights |= 0x00000001 << dwLightIndex;
2166 This->light_parameters[dwLightIndex] = *lpLight;
2168 /* Some checks to print out nice warnings :-) */
2169 switch (lpLight->dltType) {
2170 case D3DLIGHT_DIRECTIONAL:
2171 case D3DLIGHT_POINT:
2172 /* These are handled properly... */
2173 break;
2175 case D3DLIGHT_SPOT:
2176 if ((lpLight->dvTheta != 0.0) ||
2177 (lpLight->dvTheta != lpLight->dvPhi)) {
2178 ERR("dvTheta not fully supported yet !\n");
2180 break;
2182 default:
2183 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2186 /* This will force the Light setting on next drawing of primitives */
2187 glThis->transform_state = GL_TRANSFORM_NONE;
2189 return DD_OK;
2192 HRESULT WINAPI
2193 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2194 DWORD dwLightIndex,
2195 BOOL bEnable)
2197 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2198 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2200 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2202 if (bEnable) {
2203 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2204 /* Set the default parameters.. */
2205 TRACE(" setting default light parameters...\n");
2206 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2208 glEnable(GL_LIGHT0 + dwLightIndex);
2209 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2210 /* This light gets active... Need to update its parameters to GL before the next drawing */
2211 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2213 This->active_lights |= 0x00000001 << dwLightIndex;
2214 glThis->transform_state = GL_TRANSFORM_NONE;
2216 } else {
2217 glDisable(GL_LIGHT0 + dwLightIndex);
2218 This->active_lights &= ~(0x00000001 << dwLightIndex);
2221 return DD_OK;
2224 HRESULT WINAPI
2225 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2227 ICOM_THIS(IDirect3DDeviceImpl,iface);
2228 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2230 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2232 if (dwIndex >= This->max_clipping_planes) {
2233 return DDERR_INVALIDPARAMS;
2236 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2238 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2240 /* This is to force the reset of the transformation matrices on the next drawing.
2241 * This is needed to use the correct matrices for the various clipping planes.
2243 glThis->transform_state = GL_TRANSFORM_NONE;
2245 return D3D_OK;
2248 HRESULT WINAPI
2249 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2250 LPD3DVIEWPORT7 lpData)
2252 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2253 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2255 if (TRACE_ON(ddraw)) {
2256 TRACE(" viewport is : \n");
2257 TRACE(" - dwX = %ld dwY = %ld\n",
2258 lpData->dwX, lpData->dwY);
2259 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2260 lpData->dwWidth, lpData->dwHeight);
2261 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2262 lpData->dvMinZ, lpData->dvMaxZ);
2264 This->active_viewport = *lpData;
2266 ENTER_GL();
2268 /* Set the viewport */
2269 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2270 glViewport(lpData->dwX,
2271 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2272 lpData->dwWidth, lpData->dwHeight);
2274 LEAVE_GL();
2276 return DD_OK;
2279 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2280 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2281 #else
2282 # define XCAST(fun) (void*)
2283 #endif
2285 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2287 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2288 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2289 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2290 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2291 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2292 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2293 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2294 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2295 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2296 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2297 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2298 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2299 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2300 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2301 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2302 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2303 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2304 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2305 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2306 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2307 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2308 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2309 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2310 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2311 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2312 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2313 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2314 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2315 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2316 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2317 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2318 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2319 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2320 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2321 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2322 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2323 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2324 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2325 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2326 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2327 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2328 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2329 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2330 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2331 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2332 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2333 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2334 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2335 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2336 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2339 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2340 #undef XCAST
2341 #endif
2344 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2345 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2346 #else
2347 # define XCAST(fun) (void*)
2348 #endif
2350 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2352 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2353 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2354 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2355 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2356 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2357 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2358 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2359 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2360 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2361 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2362 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2363 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2364 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2365 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2366 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2367 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2368 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2369 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2370 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2371 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2372 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2373 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2374 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2375 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2376 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2377 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2378 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2379 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2380 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2381 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2382 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2383 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2384 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2385 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2386 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2387 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2388 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2389 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2390 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2391 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2392 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2393 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2394 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2397 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2398 #undef XCAST
2399 #endif
2402 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2403 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2404 #else
2405 # define XCAST(fun) (void*)
2406 #endif
2408 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2410 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2411 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2412 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2413 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2414 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2415 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2416 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2417 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2418 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2419 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2420 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2421 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2422 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2423 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2424 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2425 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2426 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2427 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2428 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2429 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2430 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2431 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2432 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2433 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2434 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2435 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2436 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2437 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2438 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2439 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2440 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2441 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2442 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2443 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2446 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2447 #undef XCAST
2448 #endif
2451 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2452 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2453 #else
2454 # define XCAST(fun) (void*)
2455 #endif
2457 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2459 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2460 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2461 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2462 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2463 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2464 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2465 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2466 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2467 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2468 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2469 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2470 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2471 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2472 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2473 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2474 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2475 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2476 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2477 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2478 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2479 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2480 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2481 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2484 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2485 #undef XCAST
2486 #endif
2488 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2489 DWORD dwCount,
2490 LPD3DRECT lpRects,
2491 DWORD dwFlags,
2492 DWORD dwColor,
2493 D3DVALUE dvZ,
2494 DWORD dwStencil)
2496 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2497 GLboolean ztest;
2498 GLfloat old_z_clear_value;
2499 GLbitfield bitfield = 0;
2500 GLint old_stencil_clear_value;
2501 GLfloat old_color_clear_value[4];
2502 D3DRECT rect;
2503 int i;
2505 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2506 if (TRACE_ON(ddraw)) {
2507 if (dwCount > 0) {
2508 int i;
2509 TRACE(" rectangles : \n");
2510 for (i = 0; i < dwCount; i++) {
2511 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2516 if (dwCount == 0) {
2517 /* Not sure if this is really needed... */
2518 dwCount = 1;
2519 rect.u1.x1 = 0;
2520 rect.u2.y1 = 0;
2521 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2522 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2523 lpRects = &rect;
2526 /* Clears the screen */
2527 ENTER_GL();
2529 if (glThis->state == SURFACE_MEMORY_DIRTY) {
2530 /* TODO: optimize here the case where Clear changes all the screen... */
2531 This->flush_to_framebuffer(This, NULL, glThis->lock_surf);
2533 glThis->state = SURFACE_GL;
2535 if (dwFlags & D3DCLEAR_ZBUFFER) {
2536 bitfield |= GL_DEPTH_BUFFER_BIT;
2537 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
2538 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2539 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
2540 glClearDepth(dvZ);
2541 TRACE(" depth value : %f\n", dvZ);
2543 if (dwFlags & D3DCLEAR_STENCIL) {
2544 bitfield |= GL_STENCIL_BUFFER_BIT;
2545 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
2546 glClearStencil(dwStencil);
2547 TRACE(" stencil value : %ld\n", dwStencil);
2549 if (dwFlags & D3DCLEAR_TARGET) {
2550 bitfield |= GL_COLOR_BUFFER_BIT;
2551 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
2552 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2553 ((dwColor >> 8) & 0xFF) / 255.0,
2554 ((dwColor >> 0) & 0xFF) / 255.0,
2555 ((dwColor >> 24) & 0xFF) / 255.0);
2556 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2559 glEnable(GL_SCISSOR_TEST);
2560 for (i = 0; i < dwCount; i++) {
2561 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2562 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2563 glClear(bitfield);
2565 glDisable(GL_SCISSOR_TEST);
2567 if (dwFlags & D3DCLEAR_ZBUFFER) {
2568 glDepthMask(ztest);
2569 glClearDepth(old_z_clear_value);
2571 if (dwFlags & D3DCLEAR_STENCIL) {
2572 bitfield |= GL_STENCIL_BUFFER_BIT;
2573 glClearStencil(old_stencil_clear_value);
2575 if (dwFlags & D3DCLEAR_TARGET) {
2576 bitfield |= GL_COLOR_BUFFER_BIT;
2577 glClearColor(old_color_clear_value[0],
2578 old_color_clear_value[1],
2579 old_color_clear_value[2],
2580 old_color_clear_value[3]);
2583 LEAVE_GL();
2585 return DD_OK;
2588 HRESULT
2589 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2590 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2591 DWORD dwFlags, LPDDBLTFX lpbltfx)
2593 if (dwFlags & DDBLT_COLORFILL) {
2594 /* This is easy to handle for the D3D Device... */
2595 DWORD color = lpbltfx->u5.dwFillColor;
2596 D3DRECT rect;
2598 TRACE(" executing D3D Device override.\n");
2600 if (rdst) {
2601 rect.u1.x1 = rdst->left;
2602 rect.u2.y1 = rdst->top;
2603 rect.u3.x2 = rdst->right;
2604 rect.u4.y2 = rdst->bottom;
2606 d3ddevice_clear(This->d3ddevice, rdst != NULL ? 1 : 0, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2607 return DD_OK;
2609 return DDERR_INVALIDPARAMS;
2612 HRESULT
2613 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
2614 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
2615 LPRECT rsrc, DWORD trans)
2617 return DDERR_INVALIDPARAMS;
2620 void
2621 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
2623 GLfloat height, width;
2624 GLfloat trans_mat[16];
2626 width = This->surface->surface_desc.dwWidth;
2627 height = This->surface->surface_desc.dwHeight;
2629 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
2630 to OpenGL screen coordinates (ie the upper left corner is not the same).
2631 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
2632 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
2633 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
2634 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
2635 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
2636 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
2638 glMatrixMode(GL_MODELVIEW);
2639 glLoadIdentity();
2640 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
2641 Correctness Tips section).
2643 Basically, from what I understood, if the game does not filter the font texture,
2644 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
2645 one and we will have strange artifacts (as the rounding and stuff may give different results
2646 for different pixels, ie sometimes take the left pixel, sometimes the right).
2648 glTranslatef(0.375, 0.375, 0);
2649 glMatrixMode(GL_PROJECTION);
2650 glLoadMatrixf(trans_mat);
2653 void
2654 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
2655 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
2657 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
2658 glMatrixMode(GL_MODELVIEW);
2659 glLoadMatrixf((float *) view_mat);
2661 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
2662 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
2663 GLint i;
2664 DWORD runner;
2665 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
2666 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
2667 GLdouble plane[4];
2669 plane[0] = This->clipping_planes[i].plane[0];
2670 plane[1] = This->clipping_planes[i].plane[1];
2671 plane[2] = This->clipping_planes[i].plane[2];
2672 plane[3] = This->clipping_planes[i].plane[3];
2674 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
2678 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
2679 GLint i;
2680 DWORD runner;
2682 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
2683 if (runner & This->active_lights) {
2684 switch (This->light_parameters[i].dltType) {
2685 case D3DLIGHT_DIRECTIONAL: {
2686 float direction[4];
2687 float cut_off = 180.0;
2689 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2690 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2691 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2692 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2694 direction[0] = This->light_parameters[i].dvDirection.u1.x;
2695 direction[1] = This->light_parameters[i].dvDirection.u2.y;
2696 direction[2] = This->light_parameters[i].dvDirection.u3.z;
2697 direction[3] = 0.0;
2698 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
2699 } break;
2701 case D3DLIGHT_POINT: {
2702 float position[4];
2703 float cut_off = 180.0;
2705 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2706 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2707 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2708 position[0] = This->light_parameters[i].dvPosition.u1.x;
2709 position[1] = This->light_parameters[i].dvPosition.u2.y;
2710 position[2] = This->light_parameters[i].dvPosition.u3.z;
2711 position[3] = 1.0;
2712 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2713 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2714 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2715 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2716 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2717 } break;
2719 case D3DLIGHT_SPOT: {
2720 float direction[4];
2721 float position[4];
2722 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
2724 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
2725 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
2726 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
2728 direction[0] = This->light_parameters[i].dvDirection.u1.x;
2729 direction[1] = This->light_parameters[i].dvDirection.u2.y;
2730 direction[2] = This->light_parameters[i].dvDirection.u3.z;
2731 direction[3] = 0.0;
2732 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
2733 position[0] = This->light_parameters[i].dvPosition.u1.x;
2734 position[1] = This->light_parameters[i].dvPosition.u2.y;
2735 position[2] = This->light_parameters[i].dvPosition.u3.z;
2736 position[3] = 1.0;
2737 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
2738 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
2739 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
2740 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
2741 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
2742 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
2743 } break;
2745 default:
2746 /* No warning here as it's already done at light setting */
2747 break;
2753 glMultMatrixf((float *) world_mat);
2755 if ((matrices & PROJMAT_CHANGED) != 0) {
2756 glMatrixMode(GL_PROJECTION);
2757 glLoadMatrixf((float *) proj_mat);
2761 void
2762 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
2764 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2765 DWORD tex_mat, tex_stage;
2766 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) != 0) {
2767 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
2768 /* This will force an update of the transform state at the next drawing. */
2769 glThis->transform_state = GL_TRANSFORM_NONE;
2772 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
2773 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
2775 ENTER_GL();
2776 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
2777 if (matrices & tex_mat) {
2778 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
2779 if (tex_stage == 0) {
2780 /* No multi-texturing support for now ... */
2781 glMatrixMode(GL_TEXTURE);
2782 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
2784 } else {
2785 glMatrixMode(GL_TEXTURE);
2786 glLoadIdentity();
2790 LEAVE_GL();
2794 /* TODO for both these functions :
2795 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
2796 by other OpenGL code in D3D
2797 - handle the case where no 'Begin / EndScene' was done between two locks
2798 - handle the rectangles in the unlock too
2799 - handle pitch correctly...
2801 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
2803 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
2804 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2805 BOOLEAN is_front;
2807 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2808 is_front = TRUE;
2809 if ((gl_d3d_dev->front_state != SURFACE_GL) &&
2810 (gl_d3d_dev->front_lock_surf != This)) {
2811 ERR("Change of front buffer.. Expect graphic corruptions !\n");
2813 gl_d3d_dev->front_lock_surf = This;
2814 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
2815 is_front = FALSE;
2816 if ((gl_d3d_dev->state != SURFACE_GL) &&
2817 (gl_d3d_dev->lock_surf != This)) {
2818 ERR("Change of back buffer.. Expect graphic corruptions !\n");
2820 gl_d3d_dev->lock_surf = This;
2821 } else {
2822 ERR("Wrong surface type for locking !\n");
2823 return;
2826 /* Try to acquire the device critical section */
2827 EnterCriticalSection(&(d3d_dev->crit));
2829 if (((is_front == TRUE) && (gl_d3d_dev->front_state == SURFACE_GL)) ||
2830 ((is_front == FALSE) && (gl_d3d_dev->state == SURFACE_GL))) {
2831 /* If the surface is already in memory, no need to do anything here... */
2832 GLenum buffer_type;
2833 GLenum buffer_color;
2834 RECT loc_rect;
2835 int y;
2836 char *dst;
2838 TRACE(" copying frame buffer to main memory.\n");
2840 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
2841 may only write to the device... But when we will blit it back to the screen, we need
2842 also to blit correctly the parts the application did not overwrite... */
2844 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2845 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2846 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2847 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2848 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2849 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2850 buffer_color = GL_RGB;
2851 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2852 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2853 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2854 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2855 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2856 buffer_type = GL_UNSIGNED_BYTE;
2857 buffer_color = GL_BGRA;
2858 glPixelStorei(GL_PACK_SWAP_BYTES, TRUE);
2859 } else {
2860 ERR(" unsupported pixel format at device locking.\n");
2861 return;
2864 ENTER_GL();
2866 if (is_front == TRUE)
2867 /* Application wants to lock the front buffer */
2868 glReadBuffer(GL_FRONT);
2869 else
2870 /* Application wants to lock the back buffer */
2871 glReadBuffer(GL_BACK);
2873 /* Just a hack while waiting for proper rectangle support */
2874 pRect = NULL;
2875 if (pRect == NULL) {
2876 loc_rect.top = 0;
2877 loc_rect.left = 0;
2878 loc_rect.bottom = This->surface_desc.dwHeight;
2879 loc_rect.right = This->surface_desc.dwWidth;
2880 } else {
2881 loc_rect = *pRect;
2884 dst = ((char *)This->surface_desc.lpSurface) +
2885 (loc_rect.top * This->surface_desc.u1.lPitch) + (loc_rect.left * GET_BPP(This->surface_desc));
2886 for (y = (This->surface_desc.dwHeight - loc_rect.top - 1);
2887 y >= ((int) This->surface_desc.dwHeight - (int) loc_rect.bottom);
2888 y--) {
2889 glReadPixels(loc_rect.left, y,
2890 loc_rect.right - loc_rect.left, 1,
2891 buffer_color, buffer_type, dst);
2892 dst += This->surface_desc.u1.lPitch;
2895 glPixelStorei(GL_PACK_SWAP_BYTES, FALSE);
2897 if (is_front)
2898 gl_d3d_dev->front_state = SURFACE_MEMORY;
2899 else
2900 gl_d3d_dev->state = SURFACE_MEMORY;
2902 #if 0
2903 /* I keep this code here as it's very useful to debug :-) */
2905 static int flush_count = 0;
2906 char buf[128];
2907 FILE *f;
2909 if ((++flush_count % 50) == 0) {
2910 sprintf(buf, "lock_%06d.pnm", flush_count);
2911 f = fopen(buf, "wb");
2912 DDRAW_dump_surface_to_disk(This, f);
2915 #endif
2917 LEAVE_GL();
2921 #define UNLOCK_TEX_SIZE 256
2923 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
2924 GLenum buffer_type, buffer_color;
2925 RECT loc_rect;
2926 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
2927 GLint depth_test, alpha_test, cull_face, lighting, min_tex, max_tex, tex_env, blend, stencil_test, fog;
2928 GLuint initial_texture;
2929 GLint tex_state;
2930 int x, y;
2932 /* Note : no need here to lock the 'device critical section' as we are already protected by
2933 the GL critical section. */
2935 loc_rect.top = 0;
2936 loc_rect.left = 0;
2937 loc_rect.bottom = surf->surface_desc.dwHeight;
2938 loc_rect.right = surf->surface_desc.dwWidth;
2940 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);
2942 glGetIntegerv(GL_DEPTH_TEST, &depth_test);
2943 glGetIntegerv(GL_ALPHA_TEST, &alpha_test);
2944 glGetIntegerv(GL_STENCIL_TEST, &stencil_test);
2945 glGetIntegerv(GL_CULL_FACE, &cull_face);
2946 glGetIntegerv(GL_LIGHTING, &lighting);
2947 glGetIntegerv(GL_BLEND, &blend);
2948 glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
2949 glGetIntegerv(GL_TEXTURE_2D, &tex_state);
2950 glGetIntegerv(GL_FOG, &fog);
2951 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &max_tex);
2952 glGetTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &min_tex);
2953 glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
2954 glMatrixMode(GL_TEXTURE);
2955 glLoadIdentity();
2956 /* TODO: scissor test if ever we use it ! */
2958 if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2959 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2960 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2961 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F) &&
2962 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x0000)) {
2963 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
2964 buffer_color = GL_RGB;
2965 } else if ((surf->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
2966 (surf->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2967 (surf->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2968 (surf->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF) &&
2969 (surf->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000)) {
2970 buffer_type = GL_UNSIGNED_BYTE;
2971 buffer_color = GL_BGRA;
2972 glPixelStorei(GL_UNPACK_SWAP_BYTES, TRUE);
2973 } else {
2974 ERR(" unsupported pixel format at frame buffer flush.\n");
2975 return;
2978 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
2979 d3ddevice_set_ortho(d3d_dev);
2981 glDisable(GL_DEPTH_TEST);
2982 glEnable(GL_TEXTURE_2D);
2983 glEnable(GL_SCISSOR_TEST);
2984 glDepthRange(0.0, 1.0);
2985 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
2986 glScissor(loc_rect.left, surf->surface_desc.dwHeight - loc_rect.bottom,
2987 loc_rect.right - loc_rect.left, loc_rect.bottom - loc_rect.top);
2989 if (gl_d3d_dev->unlock_tex == 0) {
2990 glGenTextures(1, &gl_d3d_dev->unlock_tex);
2991 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
2992 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
2993 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE, 0,
2994 GL_RGB, buffer_type, NULL);
2995 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2996 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2997 } else {
2998 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
3000 glPixelStorei(GL_UNPACK_ROW_LENGTH, surf->surface_desc.dwWidth);
3002 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3003 glDisable(GL_LIGHTING);
3004 glDisable(GL_CULL_FACE);
3005 glDisable(GL_ALPHA_TEST);
3006 glDisable(GL_STENCIL_TEST);
3007 glDisable(GL_BLEND);
3008 glDisable(GL_FOG);
3010 for (x = loc_rect.left; x < loc_rect.right; x += UNLOCK_TEX_SIZE) {
3011 for (y = loc_rect.top; y < loc_rect.bottom; y += UNLOCK_TEX_SIZE) {
3012 /* First, upload the texture... */
3013 int w = (x + UNLOCK_TEX_SIZE > surf->surface_desc.dwWidth) ? (surf->surface_desc.dwWidth - x) : UNLOCK_TEX_SIZE;
3014 int h = (y + UNLOCK_TEX_SIZE > surf->surface_desc.dwHeight) ? (surf->surface_desc.dwHeight - y) : UNLOCK_TEX_SIZE;
3015 glTexSubImage2D(GL_TEXTURE_2D,
3017 0, 0,
3018 w, h,
3019 buffer_color,
3020 buffer_type,
3021 ((char *) surf->surface_desc.lpSurface) + (x * GET_BPP(surf->surface_desc)) + (y * surf->surface_desc.u1.lPitch));
3022 glBegin(GL_QUADS);
3023 glColor3ub(0xFF, 0xFF, 0xFF);
3024 glTexCoord2f(0.0, 0.0);
3025 glVertex3d(x, y, 0.5);
3026 glTexCoord2f(1.0, 0.0);
3027 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3028 glTexCoord2f(1.0, 1.0);
3029 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3030 glTexCoord2f(0.0, 1.0);
3031 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3032 glEnd();
3037 /* And restore all the various states modified by this code */
3038 if (depth_test != 0) glEnable(GL_DEPTH_TEST);
3039 if (lighting != 0) glEnable(GL_LIGHTING);
3040 if (alpha_test != 0) glEnable(GL_ALPHA_TEST);
3041 if (stencil_test != 0) glEnable(GL_STENCIL_TEST);
3042 if (cull_face != 0) glEnable(GL_CULL_FACE);
3043 if (blend != 0) glEnable(GL_BLEND);
3044 if (fog != 0) glEnable(GL_FOG);
3045 glBindTexture(GL_TEXTURE_2D, initial_texture);
3046 if (tex_state == 0) glDisable(GL_TEXTURE_2D);
3047 glDisable(GL_SCISSOR_TEST);
3048 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
3049 glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
3050 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, tex_env);
3051 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
3052 glViewport(d3d_dev->active_viewport.dwX,
3053 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
3054 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
3055 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
3056 #if 0
3057 /* I keep this code here as it's very useful to debug :-) */
3059 static int flush_count = 0;
3060 char buf[128];
3061 FILE *f;
3063 if ((++flush_count % 50) == 0) {
3064 sprintf(buf, "flush_%06d.pnm", flush_count);
3065 f = fopen(buf, "wb");
3066 DDRAW_dump_surface_to_disk(surf, f);
3069 #endif
3072 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3074 BOOLEAN is_front;
3075 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3076 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3078 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3079 is_front = TRUE;
3080 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3081 is_front = FALSE;
3082 } else {
3083 ERR("Wrong surface type for locking !\n");
3084 return;
3086 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3087 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3088 if (is_front == TRUE) {
3089 GLenum prev_draw;
3090 ENTER_GL();
3091 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3092 glDrawBuffer(GL_FRONT);
3093 d3d_dev->flush_to_framebuffer(d3d_dev, pRect, gl_d3d_dev->front_lock_surf);
3094 glDrawBuffer(prev_draw);
3095 LEAVE_GL();
3096 } else {
3097 gl_d3d_dev->state = SURFACE_MEMORY_DIRTY;
3101 /* And 'frees' the device critical section */
3102 LeaveCriticalSection(&(d3d_dev->crit));
3105 static void
3106 apply_texture_state(IDirect3DDeviceImpl *This)
3108 int stage, state;
3110 /* Initialize texture stages states */
3111 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3112 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3113 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3114 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3115 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3121 HRESULT
3122 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
3124 IDirect3DDeviceImpl *object;
3125 IDirect3DDeviceGLImpl *gl_object;
3126 IDirectDrawSurfaceImpl *surf;
3127 HDC device_context;
3128 XVisualInfo *vis;
3129 int num;
3130 int tex_num;
3131 XVisualInfo template;
3132 GLenum buffer = GL_FRONT;
3133 int light;
3134 GLint max_clipping_planes = 0;
3136 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3137 if (object == NULL) return DDERR_OUTOFMEMORY;
3139 gl_object = (IDirect3DDeviceGLImpl *) object;
3141 object->ref = 1;
3142 object->d3d = d3d;
3143 object->surface = surface;
3144 object->set_context = set_context;
3145 object->clear = d3ddevice_clear;
3146 object->set_matrices = d3ddevice_set_matrices;
3147 object->matrices_updated = d3ddevice_matrices_updated;
3148 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3150 InitializeCriticalSection(&(object->crit));
3152 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3154 device_context = GetDC(surface->ddraw_owner->window);
3155 gl_object->display = get_display(device_context);
3156 gl_object->drawable = get_drawable(device_context);
3157 ReleaseDC(surface->ddraw_owner->window,device_context);
3159 ENTER_GL();
3160 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3161 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3162 if (vis == NULL) {
3163 HeapFree(GetProcessHeap(), 0, object);
3164 ERR("No visual found !\n");
3165 LEAVE_GL();
3166 return DDERR_INVALIDPARAMS;
3167 } else {
3168 TRACE(" visual found\n");
3171 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3172 NULL, GL_TRUE);
3174 if (gl_object->gl_context == NULL) {
3175 HeapFree(GetProcessHeap(), 0, object);
3176 ERR("Error in context creation !\n");
3177 LEAVE_GL();
3178 return DDERR_INVALIDPARAMS;
3179 } else {
3180 TRACE(" context created (%p)\n", gl_object->gl_context);
3183 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3184 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3185 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3186 surf->aux_ctx = (LPVOID) object;
3187 surf->aux_data = (LPVOID) gl_object->drawable;
3188 surf->aux_flip = opengl_flip;
3189 buffer = GL_BACK;
3190 break;
3193 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3194 if (surf == NULL) {
3195 TRACE(" no double buffering : drawing on the front buffer\n");
3196 buffer = GL_FRONT;
3199 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3200 IDirectDrawSurfaceImpl *surf2;
3201 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3202 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3203 TRACE(" checking surface %p :", surf2);
3204 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3205 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3206 /* Override the Lock / Unlock function for all these surfaces */
3207 surf2->lock_update_prev = surf2->lock_update;
3208 surf2->lock_update = d3ddevice_lock_update;
3209 surf2->unlock_update_prev = surf2->unlock_update;
3210 surf2->unlock_update = d3ddevice_unlock_update;
3211 /* And install also the blt / bltfast overrides */
3212 surf2->aux_blt = d3ddevice_blt;
3213 surf2->aux_bltfast = d3ddevice_bltfast;
3215 TRACE(" overiding direct surface access.\n");
3216 } else {
3217 TRACE(" no overide.\n");
3219 surf2->d3ddevice = object;
3223 /* Set the various light parameters */
3224 for (light = 0; light < MAX_LIGHTS; light++) {
3225 /* Only set the fields that are not zero-created */
3226 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3227 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3228 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3229 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3230 object->light_parameters[light].dvDirection.u3.z = 1.0;
3233 /* Allocate memory for the matrices */
3234 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3235 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3236 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3237 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3238 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3239 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3240 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3241 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3242 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3245 /* Initialisation */
3246 TRACE(" setting current context\n");
3247 object->set_context(object);
3248 TRACE(" current context set\n");
3250 /* allocate the clipping planes */
3251 glGetIntegerv(GL_MAX_CLIP_PLANES,&max_clipping_planes);
3252 if (max_clipping_planes>32) {
3253 object->max_clipping_planes=32;
3254 } else {
3255 object->max_clipping_planes = max_clipping_planes;
3257 TRACE(" capable of %d clipping planes\n", (int)object->max_clipping_planes );
3258 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3260 glHint(GL_FOG_HINT,GL_NICEST);
3262 glClearColor(0.0, 0.0, 0.0, 0.0);
3263 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3264 glDrawBuffer(buffer);
3265 glReadBuffer(buffer);
3266 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3267 LEAVE_GL();
3269 gl_object->state = SURFACE_GL;
3271 /* fill_device_capabilities(d3d->ddraw); */
3273 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3274 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3275 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3276 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3278 *obj = object;
3280 TRACE(" creating implementation at %p.\n", *obj);
3282 /* And finally warn D3D that this device is now present */
3283 object->d3d->added_device(object->d3d, object);
3285 /* FIXME: Should handle other versions than just 7 */
3286 InitDefaultStateBlock(&object->state_block, 7);
3287 /* Apply default render state and texture stage state values */
3288 apply_render_state(object, &object->state_block);
3289 apply_texture_state(object);
3291 /* And fill the fog table with the default fog value */
3292 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3294 return DD_OK;