Enable the application to create first textures and then the D3D
[wine/multimedia.git] / dlls / ddraw / d3ddevice / mesa.c
blob2e2c36ab33f2213104ed8cd289ccdb3363bf8454
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>
26 #include "windef.h"
27 #include "winerror.h"
28 #include "objbase.h"
29 #include "ddraw.h"
30 #include "d3d.h"
31 #include "wine/debug.h"
33 #include "mesa_private.h"
34 #include "main.h"
36 #include "x11drv.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
40 /* They are non-static as they are used by Direct3D in the creation function */
41 const GUID IID_D3DDEVICE_OpenGL = {
42 0x31416d44,
43 0x86ae,
44 0x11d2,
45 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
48 #ifndef HAVE_GLEXT_PROTOTYPES
49 /* This is for non-OpenGL ABI compliant glext.h headers :-) */
50 typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
51 GLsizei width, GLenum format, GLenum type,
52 const GLvoid *table);
53 #endif
55 static const float id_mat[16] = {
56 1.0, 0.0, 0.0, 0.0,
57 0.0, 1.0, 0.0, 0.0,
58 0.0, 0.0, 1.0, 0.0,
59 0.0, 0.0, 0.0, 1.0
62 static void draw_primitive_strided_7(IDirect3DDeviceImpl *This,
63 D3DPRIMITIVETYPE d3dptPrimitiveType,
64 DWORD d3dvtVertexType,
65 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
66 DWORD dwVertexCount,
67 LPWORD dwIndices,
68 DWORD dwIndexCount,
69 DWORD dwFlags) ;
71 /* retrieve the X display to use on a given DC */
72 inline static Display *get_display( HDC hdc )
74 Display *display;
75 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
77 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
78 sizeof(display), (LPSTR)&display )) display = NULL;
80 return display;
84 /* retrieve the X drawable to use on a given DC */
85 inline static Drawable get_drawable( HDC hdc )
87 Drawable drawable;
88 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
90 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
91 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
93 return drawable;
97 static BOOL opengl_flip( LPVOID display, LPVOID drawable)
99 TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
100 ENTER_GL();
101 glXSwapBuffers((Display*)display,(Drawable)drawable);
102 LEAVE_GL();
103 return TRUE;
107 /*******************************************************************************
108 * OpenGL static functions
110 static void set_context(IDirect3DDeviceImpl* This)
112 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
114 ENTER_GL();
115 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
116 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
117 ERR("Error in setting current context (context %p drawable %ld)!\n",
118 glThis->gl_context, glThis->drawable);
120 LEAVE_GL();
123 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
125 pc->dwSize = sizeof(*pc);
126 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
127 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
128 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
129 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL;
130 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
131 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
132 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
133 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
134 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
135 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
136 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
137 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
138 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
139 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
140 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
141 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
142 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
143 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
144 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
145 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
146 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
147 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
148 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
149 pc->dwStippleWidth = 32;
150 pc->dwStippleHeight = 32;
153 static void fill_opengl_caps(D3DDEVICEDESC *d1)
155 /* GLint maxlight; */
157 d1->dwSize = sizeof(*d1);
158 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
159 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
160 d1->dcmColorModel = D3DCOLOR_RGB;
161 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
162 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
163 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
164 /* D3D 7 capabilities */
165 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
166 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
167 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
168 d1->bClipping = TRUE;
169 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
170 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
171 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
172 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
173 fill_opengl_primcaps(&(d1->dpcLineCaps));
174 fill_opengl_primcaps(&(d1->dpcTriCaps));
175 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
176 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
177 d1->dwMaxBufferSize = 0;
178 d1->dwMaxVertexCount = 65536;
179 d1->dwMinTextureWidth = 1;
180 d1->dwMinTextureHeight = 1;
181 d1->dwMaxTextureWidth = 1024;
182 d1->dwMaxTextureHeight = 1024;
183 d1->dwMinStippleWidth = 1;
184 d1->dwMinStippleHeight = 1;
185 d1->dwMaxStippleWidth = 32;
186 d1->dwMaxStippleHeight = 32;
187 d1->dwMaxTextureRepeat = 16;
188 d1->dwMaxTextureAspectRatio = 1024;
189 d1->dwMaxAnisotropy = 0;
190 d1->dvGuardBandLeft = 0.0;
191 d1->dvGuardBandRight = 0.0;
192 d1->dvGuardBandTop = 0.0;
193 d1->dvGuardBandBottom = 0.0;
194 d1->dvExtentsAdjust = 0.0;
195 d1->dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
196 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
197 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
198 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
199 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
200 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
203 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
205 D3DDEVICEDESC d1;
207 /* Copy first D3D1/2/3 capabilities */
208 fill_opengl_caps(&d1);
210 /* And fill the D3D7 one with it */
211 d->dwDevCaps = d1.dwDevCaps;
212 d->dpcLineCaps = d1.dpcLineCaps;
213 d->dpcTriCaps = d1.dpcTriCaps;
214 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
215 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
216 d->dwMinTextureWidth = d1.dwMinTextureWidth;
217 d->dwMinTextureHeight = d1.dwMinTextureHeight;
218 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
219 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
220 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
221 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
222 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
223 d->dvGuardBandLeft = d1.dvGuardBandLeft;
224 d->dvGuardBandTop = d1.dvGuardBandTop;
225 d->dvGuardBandRight = d1.dvGuardBandRight;
226 d->dvGuardBandBottom = d1.dvGuardBandBottom;
227 d->dvExtentsAdjust = d1.dvExtentsAdjust;
228 d->dwStencilCaps = d1.dwStencilCaps;
229 d->dwFVFCaps = d1.dwFVFCaps;
230 d->dwTextureOpCaps = d1.dwTextureOpCaps;
231 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
232 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
233 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
234 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
235 d->deviceGUID = IID_IDirect3DTnLHalDevice;
236 d->wMaxUserClipPlanes = 1;
237 d->wMaxVertexBlendMatrices = 0;
238 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
239 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
240 d->dwReserved1 = 0;
241 d->dwReserved2 = 0;
242 d->dwReserved3 = 0;
243 d->dwReserved4 = 0;
246 #if 0 /* TODO : fix this and add multitexturing and other needed stuff */
247 static void fill_device_capabilities(IDirectDrawImpl* ddraw)
249 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
250 const char *ext_string;
251 Mesa_DeviceCapabilities *devcap;
253 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
254 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
256 ENTER_GL();
257 ext_string = glGetString(GL_EXTENSIONS);
258 /* Query for the ColorTable Extension */
259 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
260 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
261 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
262 } else {
263 TRACE("Color table extension not found.\n");
265 LEAVE_GL();
267 #endif
271 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context)
273 D3DDEVICEDESC d1, d2;
275 fill_opengl_caps(&d1);
276 d2 = d1;
278 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
279 return cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", "direct3d", &d1, &d2, context);
282 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
284 D3DDEVICEDESC7 ddesc;
286 fill_opengl_caps_7(&ddesc);
288 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
290 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
293 ULONG WINAPI
294 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
296 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
297 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
299 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
300 if (!--(This->ref)) {
301 /* Release texture associated with the device */
302 if (This->current_texture[0] != NULL)
303 IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[0], IDirect3DTexture2));
305 /* And warn the D3D object that this device is no longer active... */
306 This->d3d->removed_device(This->d3d, This);
308 ENTER_GL();
309 glXDestroyContext(glThis->display, glThis->gl_context);
310 LEAVE_GL();
312 HeapFree(GetProcessHeap(), 0, This);
313 return 0;
315 return This->ref;
318 HRESULT WINAPI
319 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
320 LPD3DDEVICEDESC lpD3DHWDevDesc,
321 LPD3DDEVICEDESC lpD3DHELDevDesc)
323 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
324 D3DDEVICEDESC desc;
325 DWORD dwSize;
327 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
329 fill_opengl_caps(&desc);
330 dwSize = lpD3DHWDevDesc->dwSize;
331 memset(lpD3DHWDevDesc, 0, dwSize);
332 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
334 dwSize = lpD3DHELDevDesc->dwSize;
335 memset(lpD3DHELDevDesc, 0, dwSize);
336 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
338 TRACE(" returning caps : (no dump function yet)\n");
340 return DD_OK;
343 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
344 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
345 LPVOID context)
347 DDSURFACEDESC sdesc;
348 LPDDPIXELFORMAT pformat;
350 /* Do the texture enumeration */
351 sdesc.dwSize = sizeof(DDSURFACEDESC);
352 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
353 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
354 pformat = &(sdesc.ddpfPixelFormat);
355 pformat->dwSize = sizeof(DDPIXELFORMAT);
356 pformat->dwFourCC = 0;
358 TRACE("Enumerating GL_RGBA unpacked (32)\n");
359 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
360 pformat->u1.dwRGBBitCount = 32;
361 pformat->u2.dwRBitMask = 0xFF000000;
362 pformat->u3.dwGBitMask = 0x00FF0000;
363 pformat->u4.dwBBitMask = 0x0000FF00;
364 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
365 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
366 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
368 TRACE("Enumerating GL_RGB unpacked (24)\n");
369 pformat->dwFlags = DDPF_RGB;
370 pformat->u1.dwRGBBitCount = 24;
371 pformat->u2.dwRBitMask = 0x00FF0000;
372 pformat->u3.dwGBitMask = 0x0000FF00;
373 pformat->u4.dwBBitMask = 0x000000FF;
374 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
375 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
376 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
378 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
379 pformat->dwFlags = DDPF_RGB;
380 pformat->u1.dwRGBBitCount = 16;
381 pformat->u2.dwRBitMask = 0x0000F800;
382 pformat->u3.dwGBitMask = 0x000007E0;
383 pformat->u4.dwBBitMask = 0x0000001F;
384 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
385 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
386 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
388 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
389 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
390 pformat->u1.dwRGBBitCount = 16;
391 pformat->u2.dwRBitMask = 0x0000F800;
392 pformat->u3.dwGBitMask = 0x000007C0;
393 pformat->u4.dwBBitMask = 0x0000003E;
394 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
395 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
396 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
398 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
399 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
400 pformat->u1.dwRGBBitCount = 16;
401 pformat->u2.dwRBitMask = 0x0000F000;
402 pformat->u3.dwGBitMask = 0x00000F00;
403 pformat->u4.dwBBitMask = 0x000000F0;
404 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
405 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
406 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
408 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (16)\n");
409 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
410 pformat->u1.dwRGBBitCount = 16;
411 pformat->u2.dwRBitMask = 0x00007C00;
412 pformat->u3.dwGBitMask = 0x000003E0;
413 pformat->u4.dwBBitMask = 0x0000001F;
414 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
415 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
416 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
418 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
419 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
420 pformat->u1.dwRGBBitCount = 16;
421 pformat->u2.dwRBitMask = 0x00000F00;
422 pformat->u3.dwGBitMask = 0x000000F0;
423 pformat->u4.dwBBitMask = 0x0000000F;
424 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
425 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
426 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
428 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
429 pformat->dwFlags = DDPF_RGB;
430 pformat->u1.dwRGBBitCount = 8;
431 pformat->u2.dwRBitMask = 0x000000E0;
432 pformat->u3.dwGBitMask = 0x0000001C;
433 pformat->u4.dwBBitMask = 0x00000003;
434 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
435 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
436 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
438 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
439 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
440 pformat->u1.dwRGBBitCount = 16;
441 pformat->u2.dwRBitMask = 0x00007C00;
442 pformat->u3.dwGBitMask = 0x000003E0;
443 pformat->u4.dwBBitMask = 0x0000001F;
444 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
445 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
446 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
448 TRACE("Enumerating Paletted (8)\n");
449 pformat->dwFlags = DDPF_PALETTEINDEXED8;
450 pformat->u1.dwRGBBitCount = 8;
451 pformat->u2.dwRBitMask = 0x00000000;
452 pformat->u3.dwGBitMask = 0x00000000;
453 pformat->u4.dwBBitMask = 0x00000000;
454 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
455 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
456 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
458 TRACE("End of enumeration\n");
459 return DD_OK;
463 HRESULT
464 d3ddevice_find(IDirect3DImpl *d3d,
465 LPD3DFINDDEVICESEARCH lpD3DDFS,
466 LPD3DFINDDEVICERESULT lplpD3DDevice)
468 D3DDEVICEDESC desc;
470 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
471 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
472 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
473 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
475 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
476 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
477 if ((IsEqualGUID( &IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
478 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0)) {
479 TRACE(" no match for this GUID.\n");
480 return DDERR_INVALIDPARAMS;
484 /* Now return our own GUID */
485 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
486 fill_opengl_caps(&desc);
487 lplpD3DDevice->ddHwDesc = desc;
488 lplpD3DDevice->ddSwDesc = desc;
490 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
492 return D3D_OK;
495 HRESULT WINAPI
496 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
497 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
498 LPVOID lpArg)
500 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
501 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
502 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
505 HRESULT WINAPI
506 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
507 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
508 LPVOID lpArg)
510 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
511 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
512 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
515 HRESULT WINAPI
516 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
517 D3DRENDERSTATETYPE dwRenderStateType,
518 DWORD dwRenderState)
520 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
521 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
522 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
524 /* Call the render state functions */
525 set_render_state(dwRenderStateType, dwRenderState, &(glThis->render_state));
527 return DD_OK;
530 HRESULT WINAPI
531 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
532 D3DLIGHTSTATETYPE dwLightStateType,
533 DWORD dwLightState)
535 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
536 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
538 switch (dwLightStateType) {
539 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
540 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
542 if (mat != NULL) {
543 ENTER_GL();
544 mat->activate(mat);
545 LEAVE_GL();
546 } else {
547 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
549 } break;
551 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
552 float light[4];
554 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
555 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
556 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
557 light[3] = 1.0;
558 ENTER_GL();
559 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
560 LEAVE_GL();
561 } break;
563 #define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
564 UNSUP(COLORMODEL);
565 UNSUP(FOGMODE);
566 UNSUP(FOGSTART);
567 UNSUP(FOGEND);
568 UNSUP(FOGDENSITY);
569 UNSUP(COLORVERTEX);
570 #undef UNSUP
572 default:
573 TRACE("Unexpected Light State Type\n");
574 return DDERR_INVALIDPARAMS;
577 return DD_OK;
580 HRESULT WINAPI
581 GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform(LPDIRECT3DDEVICE7 iface,
582 D3DTRANSFORMSTATETYPE dtstTransformStateType,
583 LPD3DMATRIX lpD3DMatrix)
585 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
586 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
588 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dtstTransformStateType, lpD3DMatrix);
590 ENTER_GL();
592 /* Using a trial and failure approach, I found that the order of
593 Direct3D transformations that works best is :
595 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
597 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
598 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
600 If anyone has a good explanation of the three different matrices in
601 the SDK online documentation, feel free to point it to me. For example,
602 which matrices transform lights ? In OpenGL only the PROJECTION matrix
603 transform the lights, not the MODELVIEW. Using the matrix names, I
604 supposed that PROJECTION and VIEW (all 'camera' related names) do
605 transform lights, but WORLD do not. It may be wrong though... */
607 /* After reading through both OpenGL and Direct3D documentations, I
608 thought that D3D matrices were written in 'line major mode' transposed
609 from OpenGL's 'column major mode'. But I found out that a simple memcpy
610 works fine to transfer one matrix format to the other (it did not work
611 when transposing)....
613 So :
614 1) are the documentations wrong
615 2) does the matrix work even if they are not read correctly
616 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
617 loading using glLoadMatrix ?
619 Anyway, I always use 'conv_mat' to transfer the matrices from one format
620 to the other so that if I ever find out that I need to transpose them, I
621 will able to do it quickly, only by changing the macro conv_mat. */
623 switch (dtstTransformStateType) {
624 case D3DTRANSFORMSTATE_WORLD: {
625 TRACE(" D3DTRANSFORMSTATE_WORLD :\n");
626 conv_mat(lpD3DMatrix, glThis->world_mat);
627 glMatrixMode(GL_MODELVIEW);
628 glLoadMatrixf((float *) glThis->view_mat);
629 glMultMatrixf((float *) glThis->world_mat);
630 } break;
632 case D3DTRANSFORMSTATE_VIEW: {
633 TRACE(" D3DTRANSFORMSTATE_VIEW :\n");
634 conv_mat(lpD3DMatrix, glThis->view_mat);
635 glMatrixMode(GL_MODELVIEW);
636 glLoadMatrixf((float *) glThis->view_mat);
637 glMultMatrixf((float *) glThis->world_mat);
638 } break;
640 case D3DTRANSFORMSTATE_PROJECTION: {
641 TRACE(" D3DTRANSFORMSTATE_PROJECTION :\n");
642 conv_mat(lpD3DMatrix, glThis->proj_mat);
643 glMatrixMode(GL_PROJECTION);
644 glLoadMatrixf((float *) glThis->proj_mat);
645 } break;
647 default:
648 ERR("Unknown transform type %08x !!!\n", dtstTransformStateType);
649 break;
651 LEAVE_GL();
653 /* And set the 'matrix changed' flag */
654 glThis->matrices_changed = TRUE;
656 return DD_OK;
659 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
661 switch (d3dpt) {
662 case D3DPT_POINTLIST:
663 TRACE("Start POINTS\n");
664 glBegin(GL_POINTS);
665 break;
667 case D3DPT_LINELIST:
668 TRACE("Start LINES\n");
669 glBegin(GL_LINES);
670 break;
672 case D3DPT_LINESTRIP:
673 TRACE("Start LINE_STRIP\n");
674 glBegin(GL_LINE_STRIP);
675 break;
677 case D3DPT_TRIANGLELIST:
678 TRACE("Start TRIANGLES\n");
679 glBegin(GL_TRIANGLES);
680 break;
682 case D3DPT_TRIANGLESTRIP:
683 TRACE("Start TRIANGLE_STRIP\n");
684 glBegin(GL_TRIANGLE_STRIP);
685 break;
687 case D3DPT_TRIANGLEFAN:
688 TRACE("Start TRIANGLE_FAN\n");
689 glBegin(GL_TRIANGLE_FAN);
690 break;
692 default:
693 TRACE("Unhandled primitive\n");
694 break;
698 static void draw_primitive_handle_GL_state(IDirect3DDeviceGLImpl *glThis,
699 BOOLEAN vertex_transformed,
700 BOOLEAN vertex_lit) {
701 /* Puts GL in the correct lighting / transformation mode */
702 if ((vertex_transformed == FALSE) &&
703 ((glThis->last_vertices_transformed == TRUE) ||
704 (glThis->matrices_changed == TRUE))) {
705 /* Need to put the correct transformation again if we go from Transformed
706 vertices to non-transformed ones.
708 glMatrixMode(GL_MODELVIEW);
709 glLoadMatrixf((float *) glThis->view_mat);
710 glMultMatrixf((float *) glThis->world_mat);
711 glMatrixMode(GL_PROJECTION);
712 glLoadMatrixf((float *) glThis->proj_mat);
713 } else if ((vertex_transformed == TRUE) &&
714 ((glThis->last_vertices_transformed == FALSE) ||
715 (glThis->matrices_changed == TRUE))) {
716 GLfloat height, width;
717 GLfloat trans_mat[16];
719 width = glThis->parent.surface->surface_desc.dwWidth;
720 height = glThis->parent.surface->surface_desc.dwHeight;
722 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
723 to OpenGL screen coordinates (ie the upper left corner is not the same).
724 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
725 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
726 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
727 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
728 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
729 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
731 glMatrixMode(GL_MODELVIEW);
732 glLoadIdentity();
733 glMatrixMode(GL_PROJECTION);
734 glLoadMatrixf(trans_mat);
736 glThis->matrices_changed = FALSE;
738 if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == FALSE)) {
739 glEnable(GL_LIGHTING);
740 } else if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == TRUE)) {
741 glDisable(GL_LIGHTING);
744 /* And save the current state */
745 glThis->last_vertices_transformed = vertex_transformed;
746 glThis->last_vertices_lit = vertex_lit;
750 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
751 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
753 D3DDRAWPRIMITIVESTRIDEDDATA strided;
755 switch (d3dvt) {
756 case D3DVT_VERTEX: {
757 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
758 strided.position.dwStride = sizeof(D3DVERTEX);
759 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
760 strided.normal.dwStride = sizeof(D3DVERTEX);
761 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
762 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
763 draw_primitive_strided_7(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
764 } break;
766 case D3DVT_LVERTEX: {
767 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
768 strided.position.dwStride = sizeof(D3DLVERTEX);
769 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
770 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
771 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
772 strided.specular.dwStride = sizeof(D3DLVERTEX);
773 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
774 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
775 draw_primitive_strided_7(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
776 } break;
778 case D3DVT_TLVERTEX: {
779 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
780 strided.position.dwStride = sizeof(D3DTLVERTEX);
781 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
782 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
783 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
784 strided.specular.dwStride = sizeof(D3DTLVERTEX);
785 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
786 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
787 draw_primitive_strided_7(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
788 } break;
790 default:
791 FIXME("Unhandled vertex type\n");
792 break;
796 HRESULT WINAPI
797 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
798 D3DPRIMITIVETYPE d3dptPrimitiveType,
799 D3DVERTEXTYPE d3dvtVertexType,
800 LPVOID lpvVertices,
801 DWORD dwVertexCount,
802 DWORD dwFlags)
804 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
805 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
807 ENTER_GL();
808 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
809 LEAVE_GL();
811 return DD_OK;
814 HRESULT WINAPI
815 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
816 D3DPRIMITIVETYPE d3dptPrimitiveType,
817 D3DVERTEXTYPE d3dvtVertexType,
818 LPVOID lpvVertices,
819 DWORD dwVertexCount,
820 LPWORD dwIndices,
821 DWORD dwIndexCount,
822 DWORD dwFlags)
824 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
825 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
827 ENTER_GL();
828 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
829 LEAVE_GL();
831 return DD_OK;
834 HRESULT WINAPI
835 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
836 LPD3DEXECUTEBUFFERDESC lpDesc,
837 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
838 IUnknown* pUnkOuter)
840 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
841 IDirect3DExecuteBufferImpl *ret;
842 HRESULT ret_value;
844 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
846 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
847 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
849 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
851 return ret_value;
854 DWORD get_flexible_vertex_size(DWORD d3dvtVertexType, DWORD *elements)
856 DWORD size = 0;
857 DWORD elts = 0;
859 if (d3dvtVertexType & D3DFVF_NORMAL) { size += 3 * sizeof(D3DVALUE); elts += 1; }
860 if (d3dvtVertexType & D3DFVF_DIFFUSE) { size += sizeof(DWORD); elts += 1; }
861 if (d3dvtVertexType & D3DFVF_SPECULAR) { size += sizeof(DWORD); elts += 1; }
862 switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
863 case D3DFVF_XYZ: size += 3 * sizeof(D3DVALUE); elts += 1; break;
864 case D3DFVF_XYZRHW: size += 4 * sizeof(D3DVALUE); elts += 1; break;
865 default: TRACE(" matrix weighting not handled yet...\n");
867 size += 2 * sizeof(D3DVALUE) * ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
868 elts += (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
870 if (elements) *elements = elts;
872 return size;
875 void dump_flexible_vertex(DWORD d3dvtVertexType)
877 static const flag_info flags[] = {
878 FE(D3DFVF_NORMAL),
879 FE(D3DFVF_RESERVED1),
880 FE(D3DFVF_DIFFUSE),
881 FE(D3DFVF_SPECULAR)
883 if (d3dvtVertexType & D3DFVF_RESERVED0) DPRINTF("D3DFVF_RESERVED0 ");
884 switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
885 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
886 GEN_CASE(D3DFVF_XYZ);
887 GEN_CASE(D3DFVF_XYZRHW);
888 GEN_CASE(D3DFVF_XYZB1);
889 GEN_CASE(D3DFVF_XYZB2);
890 GEN_CASE(D3DFVF_XYZB3);
891 GEN_CASE(D3DFVF_XYZB4);
892 GEN_CASE(D3DFVF_XYZB5);
894 DDRAW_dump_flags_(d3dvtVertexType, flags, sizeof(flags)/sizeof(flags[0]), FALSE);
895 switch (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) {
896 GEN_CASE(D3DFVF_TEX0);
897 GEN_CASE(D3DFVF_TEX1);
898 GEN_CASE(D3DFVF_TEX2);
899 GEN_CASE(D3DFVF_TEX3);
900 GEN_CASE(D3DFVF_TEX4);
901 GEN_CASE(D3DFVF_TEX5);
902 GEN_CASE(D3DFVF_TEX6);
903 GEN_CASE(D3DFVF_TEX7);
904 GEN_CASE(D3DFVF_TEX8);
906 #undef GEN_CASE
907 DPRINTF("\n");
910 /* These are the various handler used in the generic path */
911 inline static void handle_xyz(D3DVALUE *coords) {
912 glVertex3fv(coords);
914 inline static void handle_xyzrhw(D3DVALUE *coords) {
915 if (coords[3] < 0.00001)
916 glVertex3fv(coords);
917 else {
918 GLfloat w = 1.0 / coords[3];
920 glVertex4f(coords[0] * w,
921 coords[1] * w,
922 coords[2] * w,
926 inline static void handle_normal(D3DVALUE *coords) {
927 glNormal3fv(coords);
929 inline static void handle_specular(DWORD *color) {
930 /* Specular not handled yet properly... */
932 inline static void handle_diffuse(DWORD *color) {
933 glColor4ub((*color >> 16) & 0xFF,
934 (*color >> 8) & 0xFF,
935 (*color >> 0) & 0xFF,
936 (*color >> 24) & 0xFF);
938 inline static void handle_diffuse_and_specular(DWORD *color_d, DWORD *color_s) {
939 glColor4ub((*color_d >> 16) & 0xFF,
940 (*color_d >> 8) & 0xFF,
941 (*color_d >> 0) & 0xFF,
942 (*color_d >> 24) & 0xFF);
944 inline static void handle_texture(D3DVALUE *coords) {
945 glTexCoord2fv(coords);
947 inline static void handle_textures(D3DVALUE *coords, int tex_index) {
948 /* For the moment, draw only the first texture.. */
949 if (tex_index == 0) glTexCoord2fv(coords);
952 static void draw_primitive_strided_7(IDirect3DDeviceImpl *This,
953 D3DPRIMITIVETYPE d3dptPrimitiveType,
954 DWORD d3dvtVertexType,
955 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
956 DWORD dwVertexCount,
957 LPWORD dwIndices,
958 DWORD dwIndexCount,
959 DWORD dwFlags)
961 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
962 if (TRACE_ON(ddraw)) {
963 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
966 ENTER_GL();
967 draw_primitive_handle_GL_state(glThis,
968 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
969 (d3dvtVertexType & D3DFVF_NORMAL) == 0);
970 draw_primitive_start_GL(d3dptPrimitiveType);
972 /* Some fast paths first before the generic case.... */
973 if (d3dvtVertexType == D3DFVF_VERTEX) {
974 int index;
976 for (index = 0; index < dwIndexCount; index++) {
977 int i = (dwIndices == NULL) ? index : dwIndices[index];
978 D3DVALUE *normal =
979 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
980 D3DVALUE *tex_coord =
981 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
982 D3DVALUE *position =
983 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
985 handle_normal(normal);
986 handle_texture(tex_coord);
987 handle_xyz(position);
989 TRACE(" %f %f %f / %f %f %f (%f %f)\n",
990 position[0], position[1], position[2],
991 normal[0], normal[1], normal[2],
992 tex_coord[0], tex_coord[1]);
994 } else if (d3dvtVertexType == D3DFVF_TLVERTEX) {
995 int index;
997 for (index = 0; index < dwIndexCount; index++) {
998 int i = (dwIndices == NULL) ? index : dwIndices[index];
999 DWORD *color_d =
1000 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1001 DWORD *color_s =
1002 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1003 D3DVALUE *tex_coord =
1004 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1005 D3DVALUE *position =
1006 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1008 handle_diffuse_and_specular(color_d, color_s);
1009 handle_texture(tex_coord);
1010 handle_xyzrhw(position);
1012 TRACE(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1013 position[0], position[1], position[2], position[3],
1014 (*color_d >> 16) & 0xFF,
1015 (*color_d >> 8) & 0xFF,
1016 (*color_d >> 0) & 0xFF,
1017 (*color_d >> 24) & 0xFF,
1018 (*color_s >> 16) & 0xFF,
1019 (*color_s >> 8) & 0xFF,
1020 (*color_s >> 0) & 0xFF,
1021 (*color_s >> 24) & 0xFF,
1022 tex_coord[0], tex_coord[1]);
1024 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1025 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1026 /* This is the 'slow path' but that should support all possible vertex formats out there...
1027 Note that people should write a fast path for all vertex formats out there...
1029 int index;
1030 for (index = 0; index < dwIndexCount; index++) {
1031 int i = (dwIndices == NULL) ? index : dwIndices[index];
1033 if (d3dvtVertexType & D3DFVF_NORMAL) {
1034 D3DVALUE *normal =
1035 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1036 handle_normal(normal);
1038 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1039 DWORD *color_d =
1040 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1041 DWORD *color_s =
1042 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1043 handle_diffuse_and_specular(color_d, color_s);
1044 } else {
1045 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1046 DWORD *color_s =
1047 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1048 handle_specular(color_s);
1049 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1050 DWORD *color_d =
1051 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1052 handle_diffuse(color_d);
1056 if (((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT) == 1) {
1057 /* Special case for single texture... */
1058 D3DVALUE *tex_coord =
1059 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1060 handle_texture(tex_coord);
1061 } else {
1062 int tex_index;
1063 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1064 D3DVALUE *tex_coord =
1065 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1066 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1067 handle_textures(tex_coord, tex_index);
1070 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1071 D3DVALUE *position =
1072 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1073 handle_xyz(position);
1074 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1075 D3DVALUE *position =
1076 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1077 handle_xyzrhw(position);
1080 if (TRACE_ON(ddraw)) {
1081 int tex_index;
1083 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1084 D3DVALUE *position =
1085 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1086 TRACE(" %f %f %f", position[0], position[1], position[2]);
1087 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1088 D3DVALUE *position =
1089 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1090 TRACE(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1092 if (d3dvtVertexType & D3DFVF_NORMAL) {
1093 D3DVALUE *normal =
1094 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1095 DPRINTF(" / %f %f %f", normal[0], normal[1], normal[2]);
1097 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1098 DWORD *color_d =
1099 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1100 DPRINTF(" / %02lx %02lx %02lx %02lx",
1101 (*color_d >> 16) & 0xFF,
1102 (*color_d >> 8) & 0xFF,
1103 (*color_d >> 0) & 0xFF,
1104 (*color_d >> 24) & 0xFF);
1106 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1107 DWORD *color_s =
1108 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1109 DPRINTF(" / %02lx %02lx %02lx %02lx",
1110 (*color_s >> 16) & 0xFF,
1111 (*color_s >> 8) & 0xFF,
1112 (*color_s >> 0) & 0xFF,
1113 (*color_s >> 24) & 0xFF);
1115 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1116 D3DVALUE *tex_coord =
1117 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1118 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1119 DPRINTF(" / %f %f", tex_coord[0], tex_coord[1]);
1121 DPRINTF("\n");
1124 } else {
1125 ERR(" matrix weighting not handled yet....\n");
1128 glEnd();
1129 LEAVE_GL();
1130 TRACE("End\n");
1133 static void draw_primitive_7(IDirect3DDeviceImpl *This,
1134 D3DPRIMITIVETYPE d3dptPrimitiveType,
1135 DWORD d3dvtVertexType,
1136 LPVOID lpvVertices,
1137 DWORD dwVertexCount,
1138 LPWORD dwIndices,
1139 DWORD dwIndexCount,
1140 DWORD dwFlags)
1142 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1143 int current_offset = 0;
1144 int tex_index;
1146 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1147 strided.position.lpvData = lpvVertices;
1148 current_offset += 3 * sizeof(D3DVALUE);
1149 } else {
1150 strided.position.lpvData = lpvVertices;
1151 current_offset += 4 * sizeof(D3DVALUE);
1153 if (d3dvtVertexType & D3DFVF_NORMAL) {
1154 strided.normal.lpvData = ((char *) lpvVertices) + current_offset;
1155 current_offset += 3 * sizeof(D3DVALUE);
1157 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1158 strided.diffuse.lpvData = ((char *) lpvVertices) + current_offset;
1159 current_offset += sizeof(DWORD);
1161 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1162 strided.specular.lpvData = ((char *) lpvVertices) + current_offset;
1163 current_offset += sizeof(DWORD);
1165 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1166 strided.textureCoords[tex_index].lpvData = ((char *) lpvVertices) + current_offset;
1167 current_offset += 2 * sizeof(D3DVALUE);
1169 strided.position.dwStride = current_offset;
1170 strided.normal.dwStride = current_offset;
1171 strided.diffuse.dwStride = current_offset;
1172 strided.specular.dwStride = current_offset;
1173 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++)
1174 strided.textureCoords[tex_index].dwStride = current_offset;
1176 draw_primitive_strided_7(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1179 HRESULT WINAPI
1180 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1181 D3DPRIMITIVETYPE d3dptPrimitiveType,
1182 DWORD d3dvtVertexType,
1183 LPVOID lpvVertices,
1184 DWORD dwVertexCount,
1185 DWORD dwFlags)
1187 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1188 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1190 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, NULL, dwVertexCount, dwFlags);
1192 return DD_OK;
1195 HRESULT WINAPI
1196 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1197 D3DPRIMITIVETYPE d3dptPrimitiveType,
1198 DWORD d3dvtVertexType,
1199 LPVOID lpvVertices,
1200 DWORD dwVertexCount,
1201 LPWORD dwIndices,
1202 DWORD dwIndexCount,
1203 DWORD dwFlags)
1205 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1206 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1208 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1210 return DD_OK;
1213 HRESULT WINAPI
1214 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1215 D3DPRIMITIVETYPE d3dptPrimitiveType,
1216 DWORD dwVertexType,
1217 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1218 DWORD dwVertexCount,
1219 DWORD dwFlags)
1221 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1222 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1223 draw_primitive_strided_7(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1224 return DD_OK;
1227 HRESULT WINAPI
1228 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1229 D3DPRIMITIVETYPE d3dptPrimitiveType,
1230 DWORD dwVertexType,
1231 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1232 DWORD dwVertexCount,
1233 LPWORD lpIndex,
1234 DWORD dwIndexCount,
1235 DWORD dwFlags)
1237 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1238 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1239 draw_primitive_strided_7(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1240 return DD_OK;
1243 HRESULT WINAPI
1244 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1245 DWORD dwStage,
1246 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1247 DWORD dwState)
1249 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1250 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1251 GLenum gl_state;
1253 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1255 if (TRACE_ON(ddraw)) {
1256 TRACE(" Stage type is : ");
1257 switch (d3dTexStageStateType) {
1258 #define GEN_CASE(a) case a: DPRINTF(#a " "); break
1259 GEN_CASE(D3DTSS_COLOROP);
1260 GEN_CASE(D3DTSS_COLORARG1);
1261 GEN_CASE(D3DTSS_COLORARG2);
1262 GEN_CASE(D3DTSS_ALPHAOP);
1263 GEN_CASE(D3DTSS_ALPHAARG1);
1264 GEN_CASE(D3DTSS_ALPHAARG2);
1265 GEN_CASE(D3DTSS_BUMPENVMAT00);
1266 GEN_CASE(D3DTSS_BUMPENVMAT01);
1267 GEN_CASE(D3DTSS_BUMPENVMAT10);
1268 GEN_CASE(D3DTSS_BUMPENVMAT11);
1269 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1270 GEN_CASE(D3DTSS_ADDRESS);
1271 GEN_CASE(D3DTSS_ADDRESSU);
1272 GEN_CASE(D3DTSS_ADDRESSV);
1273 GEN_CASE(D3DTSS_BORDERCOLOR);
1274 GEN_CASE(D3DTSS_MAGFILTER);
1275 GEN_CASE(D3DTSS_MINFILTER);
1276 GEN_CASE(D3DTSS_MIPFILTER);
1277 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1278 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1279 GEN_CASE(D3DTSS_MAXANISOTROPY);
1280 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1281 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1282 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1283 #undef GEN_CASE
1284 default: DPRINTF("UNKNOWN !!!");
1286 DPRINTF(" => ");
1289 switch (d3dTexStageStateType) {
1290 case D3DTSS_MINFILTER:
1291 switch ((D3DTEXTUREMINFILTER) dwState) {
1292 case D3DTFN_POINT:
1293 if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_POINT\n");
1294 gl_state = GL_NEAREST;
1295 break;
1296 case D3DTFN_LINEAR:
1297 if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_LINEAR\n");
1298 gl_state = GL_LINEAR;
1299 break;
1300 default:
1301 if (TRACE_ON(ddraw)) DPRINTF(" state unhandled.\n");
1302 gl_state = GL_LINEAR;
1303 break;
1305 glThis->render_state.min = gl_state;
1306 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_state);
1307 break;
1309 case D3DTSS_MAGFILTER:
1310 switch ((D3DTEXTUREMAGFILTER) dwState) {
1311 case D3DTFG_POINT:
1312 if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_POINT\n");
1313 gl_state = GL_NEAREST;
1314 break;
1315 case D3DTFG_LINEAR:
1316 if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_LINEAR\n");
1317 gl_state = GL_LINEAR;
1318 break;
1319 default:
1320 if (TRACE_ON(ddraw)) DPRINTF(" state unhandled.\n");
1321 gl_state = GL_LINEAR;
1322 break;
1324 glThis->render_state.mag = gl_state;
1325 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_state);
1326 break;
1328 default:
1329 if (TRACE_ON(ddraw)) DPRINTF(" unhandled.\n");
1332 return DD_OK;
1335 HRESULT WINAPI
1336 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
1337 DWORD dwStage,
1338 LPDIRECTDRAWSURFACE7 lpTexture2)
1340 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1342 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1344 if (This->current_texture[dwStage] != NULL) {
1345 /* Seems that this is not right... Need to test in real Windows
1346 IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirect3DTexture2)); */
1349 ENTER_GL();
1350 if (lpTexture2 == NULL) {
1351 TRACE(" disabling 2D texturing.\n");
1352 glBindTexture(GL_TEXTURE_2D, 0);
1353 glDisable(GL_TEXTURE_2D);
1354 } else {
1355 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
1356 IDirect3DTextureGLImpl *tex_glimpl = (IDirect3DTextureGLImpl *) tex_impl->tex_private;
1358 This->current_texture[dwStage] = tex_impl;
1359 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
1361 TRACE(" activating OpenGL texture %d.\n", tex_glimpl->tex_name);
1363 glEnable(GL_TEXTURE_2D);
1364 glBindTexture(GL_TEXTURE_2D, tex_glimpl->tex_name);
1366 LEAVE_GL();
1368 return DD_OK;
1371 HRESULT WINAPI
1372 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1373 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1375 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1376 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1378 fill_opengl_caps_7(lpD3DHELDevDesc);
1380 TRACE(" returning caps : no dump function yet.\n");
1382 return DD_OK;
1385 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1386 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
1387 #else
1388 # define XCAST(fun) (void*)
1389 #endif
1391 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
1393 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1394 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
1395 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
1396 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
1397 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
1398 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
1399 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
1400 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
1401 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
1402 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
1403 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
1404 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
1405 XCAST(SetTransform) GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
1406 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
1407 XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
1408 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
1409 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
1410 XCAST(SetMaterial) Main_IDirect3DDeviceImpl_7_SetMaterial,
1411 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
1412 XCAST(SetLight) Main_IDirect3DDeviceImpl_7_SetLight,
1413 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
1414 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
1415 XCAST(GetRenderState) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
1416 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
1417 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
1418 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
1419 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
1420 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
1421 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
1422 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
1423 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
1424 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
1425 XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawPrimitiveVB,
1426 XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB,
1427 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
1428 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_GetTexture,
1429 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
1430 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
1431 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
1432 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
1433 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
1434 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
1435 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
1436 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
1437 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
1438 XCAST(LightEnable) Main_IDirect3DDeviceImpl_7_LightEnable,
1439 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
1440 XCAST(SetClipPlane) Main_IDirect3DDeviceImpl_7_SetClipPlane,
1441 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
1442 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
1445 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1446 #undef XCAST
1447 #endif
1450 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1451 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
1452 #else
1453 # define XCAST(fun) (void*)
1454 #endif
1456 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
1458 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1459 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
1460 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
1461 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
1462 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
1463 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
1464 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
1465 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
1466 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
1467 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
1468 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
1469 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
1470 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
1471 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
1472 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
1473 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
1474 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
1475 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
1476 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
1477 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
1478 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
1479 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
1480 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
1481 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
1482 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
1483 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
1484 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
1485 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
1486 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
1487 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
1488 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
1489 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
1490 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
1491 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
1492 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
1493 XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
1494 XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
1495 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
1496 XCAST(GetTexture) Main_IDirect3DDeviceImpl_3_GetTexture,
1497 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
1498 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
1499 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
1500 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
1503 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1504 #undef XCAST
1505 #endif
1508 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1509 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
1510 #else
1511 # define XCAST(fun) (void*)
1512 #endif
1514 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
1516 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1517 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
1518 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
1519 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
1520 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
1521 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_SwapTextureHandles,
1522 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
1523 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
1524 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
1525 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
1526 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
1527 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
1528 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
1529 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
1530 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
1531 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
1532 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
1533 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
1534 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
1535 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
1536 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
1537 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
1538 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
1539 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
1540 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
1541 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
1542 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
1543 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
1544 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
1545 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
1546 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
1547 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
1548 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
1549 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
1552 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1553 #undef XCAST
1554 #endif
1557 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1558 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
1559 #else
1560 # define XCAST(fun) (void*)
1561 #endif
1563 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
1565 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1566 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
1567 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
1568 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
1569 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
1570 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
1571 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_1_SwapTextureHandles,
1572 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
1573 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
1574 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
1575 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
1576 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
1577 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
1578 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
1579 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
1580 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
1581 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
1582 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
1583 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
1584 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
1585 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
1586 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
1587 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
1590 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1591 #undef XCAST
1592 #endif
1594 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
1595 DWORD dwCount,
1596 LPD3DRECT lpRects,
1597 DWORD dwFlags,
1598 DWORD dwColor,
1599 D3DVALUE dvZ,
1600 DWORD dwStencil)
1602 GLboolean ztest;
1603 GLfloat old_z_clear_value;
1604 GLbitfield bitfield = 0;
1605 GLint old_stencil_clear_value;
1606 GLfloat old_color_clear_value[4];
1608 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
1609 if (TRACE_ON(ddraw)) {
1610 int i;
1611 TRACE(" rectangles : \n");
1612 for (i = 0; i < dwCount; i++) {
1613 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
1617 if (dwCount != 1) {
1618 WARN(" Warning, this function only for now clears the whole screen...\n");
1621 /* Clears the screen */
1622 ENTER_GL();
1623 if (dwFlags & D3DCLEAR_ZBUFFER) {
1624 bitfield |= GL_DEPTH_BUFFER_BIT;
1625 glGetBooleanv(GL_DEPTH_WRITEMASK, &ztest);
1626 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
1627 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &old_z_clear_value);
1628 glClearDepth(dvZ);
1629 TRACE(" depth value : %f\n", dvZ);
1631 if (dwFlags & D3DCLEAR_STENCIL) {
1632 bitfield |= GL_STENCIL_BUFFER_BIT;
1633 glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &old_stencil_clear_value);
1634 glClearStencil(dwStencil);
1635 TRACE(" stencil value : %ld\n", dwStencil);
1637 if (dwFlags & D3DCLEAR_TARGET) {
1638 bitfield |= GL_COLOR_BUFFER_BIT;
1639 glGetFloatv(GL_COLOR_CLEAR_VALUE, old_color_clear_value);
1640 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
1641 ((dwColor >> 8) & 0xFF) / 255.0,
1642 ((dwColor >> 0) & 0xFF) / 255.0,
1643 ((dwColor >> 24) & 0xFF) / 255.0);
1644 TRACE(" color value (ARGB) : %08lx\n", dwColor);
1647 glClear(bitfield);
1649 if (dwFlags & D3DCLEAR_ZBUFFER) {
1650 glDepthMask(ztest);
1651 glClearDepth(old_z_clear_value);
1653 if (dwFlags & D3DCLEAR_STENCIL) {
1654 bitfield |= GL_STENCIL_BUFFER_BIT;
1655 glClearStencil(old_stencil_clear_value);
1657 if (dwFlags & D3DCLEAR_TARGET) {
1658 bitfield |= GL_COLOR_BUFFER_BIT;
1659 glClearColor(old_color_clear_value[0],
1660 old_color_clear_value[1],
1661 old_color_clear_value[2],
1662 old_color_clear_value[3]);
1665 LEAVE_GL();
1667 return DD_OK;
1671 /* TODO for both these functions :
1672 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
1673 by other OpenGL code in D3D
1674 - handle the case where no 'Begin / EndScene' was done between two locks
1675 - handle the rectangles in the unlock too
1676 - handle pitch correctly...
1678 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
1680 /* First, check if we need to do anything */
1681 if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
1682 GLenum buffer_type;
1683 GLenum prev_read;
1684 RECT loc_rect;
1686 ENTER_GL();
1688 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1689 glFlush();
1691 WARN(" application does a lock on a 3D surface - expect slow downs.\n");
1692 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1693 /* Application wants to lock the front buffer */
1694 glReadBuffer(GL_FRONT);
1695 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1696 /* Application wants to lock the back buffer */
1697 glReadBuffer(GL_BACK);
1698 } else {
1699 WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
1702 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1703 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1704 } else {
1705 WARN(" unsupported pixel format.\n");
1706 LEAVE_GL();
1707 return;
1709 if (pRect == NULL) {
1710 loc_rect.top = 0;
1711 loc_rect.left = 0;
1712 loc_rect.bottom = This->surface_desc.dwHeight;
1713 loc_rect.right = This->surface_desc.dwWidth;
1714 } else {
1715 loc_rect = *pRect;
1717 glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
1718 GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
1719 + loc_rect.top * This->surface_desc.u1.lPitch
1720 + loc_rect.left * GET_BPP(This->surface_desc)));
1721 glReadBuffer(prev_read);
1722 LEAVE_GL();
1726 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
1728 /* First, check if we need to do anything */
1729 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
1730 GLenum buffer_type;
1731 GLenum prev_draw;
1733 ENTER_GL();
1735 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
1737 WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
1738 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1739 /* Application wants to lock the front buffer */
1740 glDrawBuffer(GL_FRONT);
1741 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1742 /* Application wants to lock the back buffer */
1743 glDrawBuffer(GL_BACK);
1744 } else {
1745 WARN(" do not support 3D surface unlocking for this surface type - trying to use default buffer.\n");
1748 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1749 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1750 } else {
1751 WARN(" unsupported pixel format.\n");
1752 LEAVE_GL();
1753 return;
1755 glRasterPos2f(0.0, 0.0);
1756 glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight,
1757 GL_RGB, buffer_type, This->surface_desc.lpSurface);
1758 glDrawBuffer(prev_draw);
1760 LEAVE_GL();
1764 HRESULT
1765 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
1767 IDirect3DDeviceImpl *object;
1768 IDirect3DDeviceGLImpl *gl_object;
1769 IDirectDrawSurfaceImpl *surf;
1770 HDC device_context;
1771 XVisualInfo *vis;
1772 int num;
1773 XVisualInfo template;
1774 GLenum buffer;
1776 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
1777 if (object == NULL) return DDERR_OUTOFMEMORY;
1779 gl_object = (IDirect3DDeviceGLImpl *) object;
1781 object->ref = 1;
1782 object->d3d = d3d;
1783 object->surface = surface;
1784 object->set_context = set_context;
1785 object->clear = d3ddevice_clear;
1787 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
1789 device_context = GetDC(surface->ddraw_owner->window);
1790 gl_object->display = get_display(device_context);
1791 gl_object->drawable = get_drawable(device_context);
1792 ReleaseDC(surface->ddraw_owner->window,device_context);
1794 ENTER_GL();
1795 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
1796 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
1797 if (vis == NULL) {
1798 HeapFree(GetProcessHeap(), 0, object);
1799 ERR("No visual found !\n");
1800 LEAVE_GL();
1801 return DDERR_INVALIDPARAMS;
1802 } else {
1803 TRACE(" visual found\n");
1806 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
1807 NULL, GL_TRUE);
1809 if (gl_object->gl_context == NULL) {
1810 HeapFree(GetProcessHeap(), 0, object);
1811 ERR("Error in context creation !\n");
1812 LEAVE_GL();
1813 return DDERR_INVALIDPARAMS;
1814 } else {
1815 TRACE(" context created (%p)\n", gl_object->gl_context);
1818 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
1819 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
1820 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
1821 surf->aux_ctx = (LPVOID) gl_object->display;
1822 surf->aux_data = (LPVOID) gl_object->drawable;
1823 surf->aux_flip = opengl_flip;
1824 buffer = GL_BACK;
1825 break;
1828 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
1829 if (surf == NULL) {
1830 TRACE(" no double buffering : drawing on the front buffer\n");
1831 buffer = GL_FRONT;
1834 for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ;
1835 for (; surf != NULL; surf = surf->next_attached) {
1836 if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
1837 ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
1838 /* Override the Lock / Unlock function for all these surfaces */
1839 surf->lock_update = d3ddevice_lock_update;
1840 surf->unlock_update = d3ddevice_unlock_update;
1842 surf->d3ddevice = object;
1845 gl_object->render_state.src = GL_ONE;
1846 gl_object->render_state.dst = GL_ZERO;
1847 gl_object->render_state.mag = GL_NEAREST;
1848 gl_object->render_state.min = GL_NEAREST;
1849 gl_object->render_state.alpha_ref = 0.0; /* No actual idea about the real default value... */
1850 gl_object->render_state.alpha_func = GL_ALWAYS; /* Here either but it seems logical */
1852 /* Allocate memory for the matrices */
1853 gl_object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1854 gl_object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1855 gl_object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1856 gl_object->matrices_changed = TRUE;
1858 memcpy(gl_object->world_mat, id_mat, 16 * sizeof(float));
1859 memcpy(gl_object->view_mat , id_mat, 16 * sizeof(float));
1860 memcpy(gl_object->proj_mat , id_mat, 16 * sizeof(float));
1862 /* Initialisation */
1863 TRACE(" setting current context\n");
1864 LEAVE_GL();
1865 object->set_context(object);
1866 ENTER_GL();
1867 TRACE(" current context set\n");
1868 glClearColor(0.0, 0.0, 0.0, 0.0);
1869 glColor3f(1.0, 1.0, 1.0);
1870 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1871 glDrawBuffer(buffer);
1872 glReadBuffer(buffer);
1873 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
1874 LEAVE_GL();
1876 /* fill_device_capabilities(d3d->ddraw); */
1878 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
1879 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
1880 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
1881 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
1883 *obj = object;
1885 TRACE(" creating implementation at %p.\n", *obj);
1887 /* And finally warn D3D that this device is now present */
1888 object->d3d->added_device(object->d3d, object);
1890 return DD_OK;