blob: e1e7101246e576f87c6ffc77b4dff7642b0084e0 [file] [log] [blame]
Marcus Meissner10ad97c2000-04-09 14:30:50 +00001/* Direct3D Device
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00002 * Copyright (c) 1998 Lionel ULMER
Vincent Béron9a624912002-05-31 23:06:46 +00003 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00004 * This file contains the MESA implementation of all the D3D devices that
5 * Wine supports.
6 *
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.
11 *
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.
16 *
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
20 */
Marcus Meissner10ad97c2000-04-09 14:30:50 +000021
Marcus Meissner10ad97c2000-04-09 14:30:50 +000022#include "config.h"
Francois Gougete5ddd262001-10-14 16:18:52 +000023
24#include <string.h>
25
Marcus Meissner10ad97c2000-04-09 14:30:50 +000026#include "windef.h"
27#include "winerror.h"
Ove Kaaven1f5315c2002-12-05 20:33:07 +000028#include "objbase.h"
Marcus Meissner10ad97c2000-04-09 14:30:50 +000029#include "ddraw.h"
30#include "d3d.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000031#include "wine/debug.h"
Marcus Meissner10ad97c2000-04-09 14:30:50 +000032
33#include "mesa_private.h"
Lionel Ulmer43c3dc42002-11-21 21:04:16 +000034#include "main.h"
Marcus Meissner10ad97c2000-04-09 14:30:50 +000035
Christian Costa427b3332002-09-27 22:01:12 +000036#include "x11drv.h"
37
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000038WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
Marcus Meissner10ad97c2000-04-09 14:30:50 +000039
Lionel Ulmer43c3dc42002-11-21 21:04:16 +000040/* They are non-static as they are used by Direct3D in the creation function */
41const GUID IID_D3DDEVICE_OpenGL = {
42 0x31416d44,
43 0x86ae,
44 0x11d2,
45 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
46};
47
Marcus Meissner10ad97c2000-04-09 14:30:50 +000048/* Define this variable if you have an unpatched Mesa 3.0 (patches are available
49 on Mesa's home page) or version 3.1b.
50
51 Version 3.1b2 should correct this bug */
52#undef HAVE_BUGGY_MESAGL
53
Lionel Ulmer1434d872000-07-23 14:23:31 +000054#ifndef HAVE_GLEXT_PROTOTYPES
55/* This is for non-OpenGL ABI compliant glext.h headers :-) */
56typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
57 GLsizei width, GLenum format, GLenum type,
58 const GLvoid *table);
59#endif
60
Lionel Ulmera8cc5f52000-07-16 14:40:35 +000061static const float id_mat[16] = {
Lionel Ulmer43c3dc42002-11-21 21:04:16 +000062 1.0, 0.0, 0.0, 0.0,
63 0.0, 1.0, 0.0, 0.0,
64 0.0, 0.0, 1.0, 0.0,
65 0.0, 0.0, 0.0, 1.0
Lionel Ulmera8cc5f52000-07-16 14:40:35 +000066};
67
Christian Costa427b3332002-09-27 22:01:12 +000068/* retrieve the X display to use on a given DC */
69inline static Display *get_display( HDC hdc )
70{
71 Display *display;
72 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
73
74 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
75 sizeof(display), (LPSTR)&display )) display = NULL;
76
77 return display;
78}
79
80
81/* retrieve the X drawable to use on a given DC */
82inline static Drawable get_drawable( HDC hdc )
83{
84 Drawable drawable;
85 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
86
87 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
88 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
89
90 return drawable;
91}
92
Christian Costab47c14a2002-10-17 01:20:52 +000093
94static BOOL opengl_flip( LPVOID display, LPVOID drawable)
95{
96 TRACE("(%p, %ld)\n",(Display*)display,(Drawable)drawable);
97 ENTER_GL();
98 glXSwapBuffers((Display*)display,(Drawable)drawable);
99 LEAVE_GL();
100 return TRUE;
101}
102
103
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000104/*******************************************************************************
105 * OpenGL static functions
106 */
Christian Costa774c5f72002-11-24 22:14:40 +0000107static void set_context(IDirect3DDeviceImpl* This)
108{
109 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
110
Christian Costa427b3332002-09-27 22:01:12 +0000111 ENTER_GL();
Christian Costa774c5f72002-11-24 22:14:40 +0000112 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
113 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
Christian Costa427b3332002-09-27 22:01:12 +0000114 ERR("Error in setting current context (context %p drawable %ld)!\n",
Christian Costa774c5f72002-11-24 22:14:40 +0000115 glThis->gl_context, glThis->drawable);
Christian Costa427b3332002-09-27 22:01:12 +0000116 }
117 LEAVE_GL();
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000118}
119
120static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
121{
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000122 pc->dwSize = sizeof(*pc);
123 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
124 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKZ;
125 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
126 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST;
127 pc->dwZCmpCaps = 0xFFFFFFFF; /* All Z test can be done */
128 pc->dwSrcBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
129 pc->dwDestBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
130 pc->dwAlphaCmpCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
131 pc->dwShadeCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
132 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
133 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
134 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
135 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST;
136 pc->dwTextureBlendCaps = 0xFFFFFFFF; /* FIXME: need REAL values */
137 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP;
138 pc->dwStippleWidth = 32;
139 pc->dwStippleHeight = 32;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000140}
141
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000142static void fill_opengl_caps(D3DDEVICEDESC *d1)
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000143{
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000144 /* GLint maxlight; */
Vincent Béron9a624912002-05-31 23:06:46 +0000145
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000146 d1->dwSize = sizeof(*d1);
147 d1->dwFlags = D3DDD_DEVCAPS | D3DDD_BCLIPPING | D3DDD_COLORMODEL | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH
148 | D3DDD_LIGHTINGCAPS | D3DDD_LINECAPS | D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT | D3DDD_TRANSFORMCAPS | D3DDD_TRICAPS;
149 d1->dcmColorModel = D3DCOLOR_RGB;
150 d1->dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
151 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000152 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000153 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
154 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
155 d1->bClipping = TRUE;
156 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
157 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
158 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
159 d1->dlcLightingCaps.dwNumLights = 16; /* glGetIntegerv(GL_MAX_LIGHTS, &maxlight); d1->dlcLightingCaps.dwNumLights = maxlight; */
160 fill_opengl_primcaps(&(d1->dpcLineCaps));
161 fill_opengl_primcaps(&(d1->dpcTriCaps));
Lionel Ulmer5261f032002-12-02 21:39:34 +0000162 d1->dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
Lionel Ulmer91c6f812002-12-15 01:17:59 +0000163 d1->dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000164 d1->dwMaxBufferSize = 0;
165 d1->dwMaxVertexCount = 65536;
166 d1->dwMinTextureWidth = 1;
167 d1->dwMinTextureHeight = 1;
168 d1->dwMaxTextureWidth = 1024;
169 d1->dwMaxTextureHeight = 1024;
170 d1->dwMinStippleWidth = 1;
171 d1->dwMinStippleHeight = 1;
172 d1->dwMaxStippleWidth = 32;
173 d1->dwMaxStippleHeight = 32;
Lionel Ulmerda0b4dc2002-11-30 01:49:08 +0000174 d1->dwMaxTextureRepeat = 16;
175 d1->dwMaxTextureAspectRatio = 1024;
176 d1->dwMaxAnisotropy = 0;
177 d1->dvGuardBandLeft = 0.0;
178 d1->dvGuardBandRight = 0.0;
179 d1->dvGuardBandTop = 0.0;
180 d1->dvGuardBandBottom = 0.0;
181 d1->dvExtentsAdjust = 0.0;
182 d1->dwStencilCaps = 0; /* TODO add proper caps according to what OpenGL can do */
183 d1->dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
184 d1->dwTextureOpCaps = 0; /* TODO add proper caps according to OpenGL multi-texture stuff */
185 d1->wMaxTextureBlendStages = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
186 d1->wMaxSimultaneousTextures = 1; /* TODO add proper caps according to OpenGL multi-texture stuff */
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000187}
188
Lionel Ulmerf4b941e2002-11-30 19:21:42 +0000189static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
190{
191 D3DDEVICEDESC d1;
192
193 /* Copy first D3D1/2/3 capabilities */
194 fill_opengl_caps(&d1);
195
196 /* And fill the D3D7 one with it */
197 d->dwDevCaps = d1.dwDevCaps;
198 d->dpcLineCaps = d1.dpcLineCaps;
199 d->dpcTriCaps = d1.dpcTriCaps;
200 d->dwDeviceRenderBitDepth = d1.dwDeviceRenderBitDepth;
201 d->dwDeviceZBufferBitDepth = d1.dwDeviceZBufferBitDepth;
202 d->dwMinTextureWidth = d1.dwMinTextureWidth;
203 d->dwMinTextureHeight = d1.dwMinTextureHeight;
204 d->dwMaxTextureWidth = d1.dwMaxTextureWidth;
205 d->dwMaxTextureHeight = d1.dwMaxTextureHeight;
206 d->dwMaxTextureRepeat = d1.dwMaxTextureRepeat;
207 d->dwMaxTextureAspectRatio = d1.dwMaxTextureAspectRatio;
208 d->dwMaxAnisotropy = d1.dwMaxAnisotropy;
209 d->dvGuardBandLeft = d1.dvGuardBandLeft;
210 d->dvGuardBandTop = d1.dvGuardBandTop;
211 d->dvGuardBandRight = d1.dvGuardBandRight;
212 d->dvGuardBandBottom = d1.dvGuardBandBottom;
213 d->dvExtentsAdjust = d1.dvExtentsAdjust;
214 d->dwStencilCaps = d1.dwStencilCaps;
215 d->dwFVFCaps = d1.dwFVFCaps;
216 d->dwTextureOpCaps = d1.dwTextureOpCaps;
217 d->wMaxTextureBlendStages = d1.wMaxTextureBlendStages;
218 d->wMaxSimultaneousTextures = d1.wMaxSimultaneousTextures;
219 d->dwMaxActiveLights = d1.dlcLightingCaps.dwNumLights;
220 d->dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
221 d->deviceGUID = IID_IDirect3DTnLHalDevice;
222 d->wMaxUserClipPlanes = 1;
Lionel Ulmerc5f38752002-11-30 19:27:19 +0000223 d->wMaxVertexBlendMatrices = 0;
Lionel Ulmerf4b941e2002-11-30 19:21:42 +0000224 d->dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG | D3DVTXPCAPS_DIRECTIONALLIGHTS |
225 D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
226 d->dwReserved1 = 0;
227 d->dwReserved2 = 0;
228 d->dwReserved3 = 0;
229 d->dwReserved4 = 0;
230}
231
Lionel Ulmerda0b4dc2002-11-30 01:49:08 +0000232#if 0 /* TODO : fix this and add multitexturing and other needed stuff */
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000233static void fill_device_capabilities(IDirectDrawImpl* ddraw)
234{
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000235 x11_dd_private *private = (x11_dd_private *) ddraw->d->private;
236 const char *ext_string;
237 Mesa_DeviceCapabilities *devcap;
Vincent Béron9a624912002-05-31 23:06:46 +0000238
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000239 private->device_capabilities = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(Mesa_DeviceCapabilities));
240 devcap = (Mesa_DeviceCapabilities *) private->device_capabilities;
Vincent Béron9a624912002-05-31 23:06:46 +0000241
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000242 ENTER_GL();
243 ext_string = glGetString(GL_EXTENSIONS);
244 /* Query for the ColorTable Extension */
245 if (strstr(ext_string, "GL_EXT_paletted_texture")) {
246 devcap->ptr_ColorTableEXT = (PFNGLCOLORTABLEEXTPROC) glXGetProcAddressARB("glColorTableEXT");
247 TRACE("Color table extension supported (function at %p)\n", devcap->ptr_ColorTableEXT);
248 } else {
249 TRACE("Color table extension not found.\n");
250 }
251 LEAVE_GL();
Lionel Ulmera8cc5f52000-07-16 14:40:35 +0000252}
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000253#endif
Lionel Ulmera8cc5f52000-07-16 14:40:35 +0000254
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000255
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000256
Lionel Ulmerb0350a32002-12-05 19:07:59 +0000257HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context)
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000258{
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000259 D3DDEVICEDESC d1, d2;
Christian Costa427b3332002-09-27 22:01:12 +0000260
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000261 fill_opengl_caps(&d1);
262 d2 = d1;
263
Lionel Ulmerb0350a32002-12-05 19:07:59 +0000264 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
265 return cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", "direct3d", &d1, &d2, context);
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000266}
267
Lionel Ulmerf4b941e2002-11-30 19:21:42 +0000268HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
269{
270 D3DDEVICEDESC7 ddesc;
271
272 fill_opengl_caps_7(&ddesc);
273
274 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
275
276 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
277}
278
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000279ULONG WINAPI
280GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
281{
282 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
283 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
284
285 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
286 if (!--(This->ref)) {
287 /* Release texture associated with the device */
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +0000288 if (This->current_texture[0] != NULL)
289 IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[0], IDirect3DTexture2));
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000290
291 ENTER_GL();
292 glXDestroyContext(glThis->display, glThis->gl_context);
293 LEAVE_GL();
294
295 HeapFree(GetProcessHeap(), 0, This);
296 return 0;
297 }
298 return This->ref;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000299}
300
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000301HRESULT WINAPI
302GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
303 LPD3DDEVICEDESC lpD3DHWDevDesc,
304 LPD3DDEVICEDESC lpD3DHELDevDesc)
305{
306 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
307 D3DDEVICEDESC desc;
308 DWORD dwSize;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000309
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000310 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
Vincent Béron9a624912002-05-31 23:06:46 +0000311
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000312 fill_opengl_caps(&desc);
313 dwSize = lpD3DHWDevDesc->dwSize;
314 memset(lpD3DHWDevDesc, 0, dwSize);
315 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
316
317 dwSize = lpD3DHELDevDesc->dwSize;
318 memset(lpD3DHELDevDesc, 0, dwSize);
319 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
320
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000321 TRACE(" returning caps : (no dump function yet)\n");
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000322
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000323 return DD_OK;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000324}
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000325
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000326static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
327 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
328 LPVOID context)
329{
330 DDSURFACEDESC sdesc;
331 LPDDPIXELFORMAT pformat;
332
333 /* Do the texture enumeration */
334 sdesc.dwSize = sizeof(DDSURFACEDESC);
335 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
336 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
337 pformat = &(sdesc.ddpfPixelFormat);
338 pformat->dwSize = sizeof(DDPIXELFORMAT);
339 pformat->dwFourCC = 0;
340
341 TRACE("Enumerating GL_RGBA unpacked (32)\n");
342 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
343 pformat->u1.dwRGBBitCount = 32;
344 pformat->u2.dwRBitMask = 0xFF000000;
345 pformat->u3.dwGBitMask = 0x00FF0000;
346 pformat->u4.dwBBitMask = 0x0000FF00;
347 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
348 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
349 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
350
351 TRACE("Enumerating GL_RGB unpacked (24)\n");
352 pformat->dwFlags = DDPF_RGB;
353 pformat->u1.dwRGBBitCount = 24;
354 pformat->u2.dwRBitMask = 0x00FF0000;
355 pformat->u3.dwGBitMask = 0x0000FF00;
356 pformat->u4.dwBBitMask = 0x000000FF;
357 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
358 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
359 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000360
361#ifndef HAVE_BUGGY_MESAGL
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000362 /* The packed texture format are buggy in Mesa. The bug was reported and corrected,
363 so that future version will work great. */
364 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
365 pformat->dwFlags = DDPF_RGB;
366 pformat->u1.dwRGBBitCount = 16;
367 pformat->u2.dwRBitMask = 0x0000F800;
368 pformat->u3.dwGBitMask = 0x000007E0;
369 pformat->u4.dwBBitMask = 0x0000001F;
370 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
371 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
372 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000373
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000374 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
375 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
376 pformat->u1.dwRGBBitCount = 16;
377 pformat->u2.dwRBitMask = 0x0000F800;
378 pformat->u3.dwGBitMask = 0x000007C0;
379 pformat->u4.dwBBitMask = 0x0000003E;
380 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
381 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
382 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000383
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000384 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
385 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
386 pformat->u1.dwRGBBitCount = 16;
387 pformat->u2.dwRBitMask = 0x0000F000;
388 pformat->u3.dwGBitMask = 0x00000F00;
389 pformat->u4.dwBBitMask = 0x000000F0;
390 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
391 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
392 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000393
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000394 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
395 pformat->dwFlags = DDPF_RGB;
396 pformat->u1.dwRGBBitCount = 8;
397 pformat->u2.dwRBitMask = 0x000000E0;
398 pformat->u3.dwGBitMask = 0x0000001C;
399 pformat->u4.dwBBitMask = 0x00000003;
400 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
401 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
402 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000403#endif
404
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000405 TRACE("Enumerating GL_ARGB (no direct OpenGL equivalent - conversion needed)\n");
406 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
407 pformat->u1.dwRGBBitCount = 16;
408 pformat->u2.dwRBitMask = 0x00007C00;
409 pformat->u3.dwGBitMask = 0x000003E0;
410 pformat->u4.dwBBitMask = 0x0000001F;
411 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
412 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
413 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
414
415 TRACE("Enumerating Paletted (8)\n");
416 pformat->dwFlags = DDPF_PALETTEINDEXED8;
417 pformat->u1.dwRGBBitCount = 8;
418 pformat->u2.dwRBitMask = 0x00000000;
419 pformat->u3.dwGBitMask = 0x00000000;
420 pformat->u4.dwBBitMask = 0x00000000;
421 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
422 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
423 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
424
425 TRACE("End of enumeration\n");
Vincent Béron9a624912002-05-31 23:06:46 +0000426 return DD_OK;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000427}
Vincent Béron9a624912002-05-31 23:06:46 +0000428
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000429
430HRESULT
431d3ddevice_find(IDirect3DImpl *d3d,
432 LPD3DFINDDEVICESEARCH lpD3DDFS,
Lionel Ulmerb0350a32002-12-05 19:07:59 +0000433 LPD3DFINDDEVICERESULT lplpD3DDevice)
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000434{
435 DWORD dwSize;
436 D3DDEVICEDESC desc;
437
438 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
439 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
440 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
441 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
442 }
443 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
444 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
445 if ((IsEqualGUID( &IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000446 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0)) {
447 TRACE(" no match for this GUID.\n");
448 return DDERR_INVALIDPARAMS;
449 }
450 }
451
Lionel Ulmerb0350a32002-12-05 19:07:59 +0000452 /* Now return our own GUID */
453 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000454 fill_opengl_caps(&desc);
455 dwSize = lplpD3DDevice->ddHwDesc.dwSize;
456 memset(&(lplpD3DDevice->ddHwDesc), 0, dwSize);
457 memcpy(&(lplpD3DDevice->ddHwDesc), &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
458 dwSize = lplpD3DDevice->ddSwDesc.dwSize;
459 memset(&(lplpD3DDevice->ddSwDesc), 0, dwSize);
460 memcpy(&(lplpD3DDevice->ddSwDesc), &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
461
462 return D3D_OK;
463}
464
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000465HRESULT WINAPI
466GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
467 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
468 LPVOID lpArg)
469{
470 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
471 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
472 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
473}
474
475HRESULT WINAPI
476GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
477 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
478 LPVOID lpArg)
479{
480 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
481 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
482 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
483}
484
485HRESULT WINAPI
486GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
487 D3DRENDERSTATETYPE dwRenderStateType,
488 DWORD dwRenderState)
489{
490 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
491 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
492 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
493
494 /* Call the render state functions */
495 set_render_state(dwRenderStateType, dwRenderState, &(glThis->render_state));
496
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000497 return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000498}
499
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000500HRESULT WINAPI
501GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
502 D3DLIGHTSTATETYPE dwLightStateType,
503 DWORD dwLightState)
504{
505 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
506 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
Vincent Béron9a624912002-05-31 23:06:46 +0000507
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000508 switch (dwLightStateType) {
509 case D3DLIGHTSTATE_MATERIAL: { /* 1 */
510 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000511
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000512 if (mat != NULL) {
513 ENTER_GL();
514 mat->activate(mat);
515 LEAVE_GL();
516 } else {
517 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
518 }
519 } break;
Vincent Béron9a624912002-05-31 23:06:46 +0000520
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000521 case D3DLIGHTSTATE_AMBIENT: { /* 2 */
522 float light[4];
Vincent Béron9a624912002-05-31 23:06:46 +0000523
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000524 light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
525 light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
526 light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
527 light[3] = 1.0;
528 ENTER_GL();
529 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
530 LEAVE_GL();
531 } break;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000532
533#define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000534 UNSUP(COLORMODEL);
535 UNSUP(FOGMODE);
536 UNSUP(FOGSTART);
537 UNSUP(FOGEND);
538 UNSUP(FOGDENSITY);
Christian Costa2db04152002-12-02 21:11:47 +0000539 UNSUP(COLORVERTEX);
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000540#undef UNSUP
Vincent Béron9a624912002-05-31 23:06:46 +0000541
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000542 default:
543 TRACE("Unexpected Light State Type\n");
544 return DDERR_INVALIDPARAMS;
545 }
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000546
Marcus Meissner3873f442000-04-10 13:45:17 +0000547 return DD_OK;
548}
549
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000550HRESULT WINAPI
551GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform(LPDIRECT3DDEVICE7 iface,
552 D3DTRANSFORMSTATETYPE dtstTransformStateType,
553 LPD3DMATRIX lpD3DMatrix)
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000554{
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000555 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
556 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
Vincent Béron9a624912002-05-31 23:06:46 +0000557
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000558 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dtstTransformStateType, lpD3DMatrix);
Vincent Béron9a624912002-05-31 23:06:46 +0000559
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000560 ENTER_GL();
Vincent Béron9a624912002-05-31 23:06:46 +0000561
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000562 /* Using a trial and failure approach, I found that the order of
563 Direct3D transformations that works best is :
Vincent Béron9a624912002-05-31 23:06:46 +0000564
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000565 ScreenCoord = ProjectionMat * ViewMat * WorldMat * ObjectCoord
Vincent Béron9a624912002-05-31 23:06:46 +0000566
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000567 As OpenGL uses only two matrices, I combined PROJECTION and VIEW into
568 OpenGL's GL_PROJECTION matrix and the WORLD into GL_MODELVIEW.
Vincent Béron9a624912002-05-31 23:06:46 +0000569
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000570 If anyone has a good explanation of the three different matrices in
571 the SDK online documentation, feel free to point it to me. For example,
572 which matrices transform lights ? In OpenGL only the PROJECTION matrix
573 transform the lights, not the MODELVIEW. Using the matrix names, I
574 supposed that PROJECTION and VIEW (all 'camera' related names) do
575 transform lights, but WORLD do not. It may be wrong though... */
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000576
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000577 /* After reading through both OpenGL and Direct3D documentations, I
578 thought that D3D matrices were written in 'line major mode' transposed
579 from OpenGL's 'column major mode'. But I found out that a simple memcpy
580 works fine to transfer one matrix format to the other (it did not work
581 when transposing)....
Vincent Béron9a624912002-05-31 23:06:46 +0000582
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000583 So :
584 1) are the documentations wrong
585 2) does the matrix work even if they are not read correctly
586 3) is Mesa's implementation of OpenGL not compliant regarding Matrix
587 loading using glLoadMatrix ?
Vincent Béron9a624912002-05-31 23:06:46 +0000588
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000589 Anyway, I always use 'conv_mat' to transfer the matrices from one format
590 to the other so that if I ever find out that I need to transpose them, I
591 will able to do it quickly, only by changing the macro conv_mat. */
Vincent Béron9a624912002-05-31 23:06:46 +0000592
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000593 switch (dtstTransformStateType) {
594 case D3DTRANSFORMSTATE_WORLD: {
Lionel Ulmer708c4b22002-11-30 19:12:32 +0000595 TRACE(" D3DTRANSFORMSTATE_WORLD :\n");
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000596 conv_mat(lpD3DMatrix, glThis->world_mat);
597 glMatrixMode(GL_MODELVIEW);
Lionel Ulmer708c4b22002-11-30 19:12:32 +0000598 glLoadMatrixf((float *) glThis->view_mat);
599 glMultMatrixf((float *) glThis->world_mat);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000600 } break;
601
602 case D3DTRANSFORMSTATE_VIEW: {
Lionel Ulmer708c4b22002-11-30 19:12:32 +0000603 TRACE(" D3DTRANSFORMSTATE_VIEW :\n");
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000604 conv_mat(lpD3DMatrix, glThis->view_mat);
Lionel Ulmer708c4b22002-11-30 19:12:32 +0000605 glMatrixMode(GL_MODELVIEW);
606 glLoadMatrixf((float *) glThis->view_mat);
607 glMultMatrixf((float *) glThis->world_mat);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000608 } break;
609
610 case D3DTRANSFORMSTATE_PROJECTION: {
Lionel Ulmer708c4b22002-11-30 19:12:32 +0000611 TRACE(" D3DTRANSFORMSTATE_PROJECTION :\n");
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000612 conv_mat(lpD3DMatrix, glThis->proj_mat);
613 glMatrixMode(GL_PROJECTION);
614 glLoadMatrixf((float *) glThis->proj_mat);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000615 } break;
616
617 default:
618 ERR("Unknown trasnform type %08x !!!\n", dtstTransformStateType);
619 break;
620 }
621 LEAVE_GL();
622
623 return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000624}
625
Lionel Ulmera6e50802002-11-30 19:19:00 +0000626static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000627{
628 switch (d3dpt) {
629 case D3DPT_POINTLIST:
630 TRACE("Start POINTS\n");
631 glBegin(GL_POINTS);
632 break;
633
634 case D3DPT_LINELIST:
635 TRACE("Start LINES\n");
636 glBegin(GL_LINES);
637 break;
638
639 case D3DPT_LINESTRIP:
640 TRACE("Start LINE_STRIP\n");
641 glBegin(GL_LINE_STRIP);
642 break;
643
644 case D3DPT_TRIANGLELIST:
645 TRACE("Start TRIANGLES\n");
646 glBegin(GL_TRIANGLES);
647 break;
648
649 case D3DPT_TRIANGLESTRIP:
650 TRACE("Start TRIANGLE_STRIP\n");
651 glBegin(GL_TRIANGLE_STRIP);
652 break;
653
654 case D3DPT_TRIANGLEFAN:
655 TRACE("Start TRIANGLE_FAN\n");
656 glBegin(GL_TRIANGLE_FAN);
657 break;
658
659 default:
660 TRACE("Unhandled primitive\n");
661 break;
662 }
663}
664
Lionel Ulmera6e50802002-11-30 19:19:00 +0000665static void draw_primitive_handle_GL_state(IDirect3DDeviceGLImpl *glThis,
666 BOOLEAN vertex_transformed,
667 BOOLEAN vertex_lit) {
668 /* Puts GL in the correct lighting / transformation mode */
669 if ((glThis->last_vertices_transformed == TRUE) && (vertex_transformed == FALSE)) {
670 /* Need to put the correct transformation again if we go from Transformed
671 vertices to non-transformed ones.
672 */
673 glMatrixMode(GL_MODELVIEW);
674 glLoadMatrixf((float *) glThis->view_mat);
675 glMultMatrixf((float *) glThis->world_mat);
676 glMatrixMode(GL_PROJECTION);
677 glLoadMatrixf((float *) glThis->proj_mat);
678 } else if ((glThis->last_vertices_transformed == FALSE) && (vertex_transformed == TRUE)) {
679 GLdouble height, width, minZ, maxZ;
680
681 glMatrixMode(GL_MODELVIEW);
682 glLoadIdentity();
683 glMatrixMode(GL_PROJECTION);
684 glLoadIdentity();
685
686 if (glThis->parent.current_viewport == NULL) {
687 ERR("No current viewport !\n");
688 /* Using standard values */
689 height = 640.0;
690 width = 480.0;
691 minZ = -10.0;
692 maxZ = 10.0;
693 } else {
694 if (glThis->parent.current_viewport->use_vp2 == 1) {
695 height = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwHeight;
696 width = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dwWidth;
697 minZ = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMinZ;
698 maxZ = (GLdouble) glThis->parent.current_viewport->viewports.vp2.dvMaxZ;
699 } else {
700 height = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwHeight;
701 width = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dwWidth;
702 minZ = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMinZ;
703 maxZ = (GLdouble) glThis->parent.current_viewport->viewports.vp1.dvMaxZ;
704 }
705 }
706 glOrtho(0.0, width, height, 0.0, -minZ, -maxZ);
707 }
708
709 if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == FALSE)) {
710 glEnable(GL_LIGHTING);
711 } else if ((glThis->last_vertices_lit == TRUE) && (vertex_lit == TRUE)) {
712 glDisable(GL_LIGHTING);
713 }
714
715 /* And save the current state */
716 glThis->last_vertices_transformed = vertex_transformed;
717 glThis->last_vertices_lit = vertex_lit;
718}
719
720
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000721inline static void draw_primitive(IDirect3DDeviceGLImpl *glThis, DWORD maxvert, WORD *index,
722 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000723{
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000724 DWORD vx_index;
725
Lionel Ulmera6e50802002-11-30 19:19:00 +0000726 draw_primitive_handle_GL_state(glThis, d3dvt == D3DVT_TLVERTEX, d3dvt != D3DVT_VERTEX);
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000727 draw_primitive_start_GL(d3dpt);
728
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000729 /* Draw the primitives */
730 for (vx_index = 0; vx_index < maxvert; vx_index++) {
731 switch (d3dvt) {
732 case D3DVT_VERTEX: {
733 D3DVERTEX *vx = ((D3DVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
734
735 glNormal3f(vx->u4.nx, vx->u5.ny, vx->u6.nz);
736 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
737 TRACE(" V: %f %f %f\n", vx->u1.x, vx->u2.y, vx->u3.z);
738 } break;
739
740 case D3DVT_LVERTEX: {
741 D3DLVERTEX *vx = ((D3DLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
742 DWORD col = vx->u4.color;
743
744 glColor3f(((col >> 16) & 0xFF) / 255.0,
745 ((col >> 8) & 0xFF) / 255.0,
746 ((col >> 0) & 0xFF) / 255.0);
747 glVertex3f(vx->u1.x, vx->u2.y, vx->u3.z);
748 TRACE(" LV: %f %f %f (%02lx %02lx %02lx)\n",
749 vx->u1.x, vx->u2.y, vx->u3.z,
750 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF));
751 } break;
752
753 case D3DVT_TLVERTEX: {
754 D3DTLVERTEX *vx = ((D3DTLVERTEX *) lpvertex) + (index == 0 ? vx_index : index[vx_index]);
755 DWORD col = vx->u5.color;
756
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000757 glColor4ub((col >> 24) & 0xFF,
758 (col >> 16) & 0xFF,
759 (col >> 8) & 0xFF,
760 (col >> 0) & 0xFF);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000761 glTexCoord2f(vx->u7.tu, vx->u8.tv);
762 if (vx->u4.rhw < 0.01)
763 glVertex3f(vx->u1.sx,
764 vx->u2.sy,
765 vx->u3.sz);
766 else
767 glVertex4f(vx->u1.sx / vx->u4.rhw,
768 vx->u2.sy / vx->u4.rhw,
769 vx->u3.sz / vx->u4.rhw,
770 1.0 / vx->u4.rhw);
771 TRACE(" TLV: %f %f %f (%02lx %02lx %02lx) (%f %f) (%f)\n",
772 vx->u1.sx, vx->u2.sy, vx->u3.sz,
773 ((col >> 16) & 0xFF), ((col >> 8) & 0xFF), ((col >> 0) & 0xFF),
774 vx->u7.tu, vx->u8.tv, vx->u4.rhw);
775 } break;
776
777 default:
778 FIXME("Unhandled vertex type\n");
779 break;
780 }
781 }
782
783 glEnd();
784 TRACE("End\n");
785}
786
787HRESULT WINAPI
788GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
789 D3DPRIMITIVETYPE d3dptPrimitiveType,
790 D3DVERTEXTYPE d3dvtVertexType,
791 LPVOID lpvVertices,
792 DWORD dwVertexCount,
793 DWORD dwFlags)
794{
795 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
796 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
797
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000798 ENTER_GL();
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000799 draw_primitive((IDirect3DDeviceGLImpl *) This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
800 LEAVE_GL();
801
802 return DD_OK;
803}
Christian Costab47c14a2002-10-17 01:20:52 +0000804
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000805HRESULT WINAPI
806GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
807 D3DPRIMITIVETYPE d3dptPrimitiveType,
808 D3DVERTEXTYPE d3dvtVertexType,
809 LPVOID lpvVertices,
810 DWORD dwVertexCount,
811 LPWORD dwIndices,
812 DWORD dwIndexCount,
813 DWORD dwFlags)
814{
815 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
816 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
817
818 ENTER_GL();
819 draw_primitive((IDirect3DDeviceGLImpl *) This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
820 LEAVE_GL();
821
822 return DD_OK;
823}
824
825HRESULT WINAPI
826GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
827 LPD3DEXECUTEBUFFERDESC lpDesc,
828 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
829 IUnknown* pUnkOuter)
830{
831 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
832 IDirect3DExecuteBufferImpl *ret;
833 HRESULT ret_value;
834
835 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
836
837 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
838 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
839
840 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
841
842 return ret_value;
843}
844
Lionel Ulmer91c6f812002-12-15 01:17:59 +0000845DWORD get_flexible_vertex_size(DWORD d3dvtVertexType, DWORD *elements)
Lionel Ulmerc5f38752002-11-30 19:27:19 +0000846{
847 DWORD size = 0;
Lionel Ulmer91c6f812002-12-15 01:17:59 +0000848 DWORD elts = 0;
Lionel Ulmerc5f38752002-11-30 19:27:19 +0000849
Lionel Ulmer91c6f812002-12-15 01:17:59 +0000850 if (d3dvtVertexType & D3DFVF_NORMAL) { size += 3 * sizeof(D3DVALUE); elts += 1; }
851 if (d3dvtVertexType & D3DFVF_DIFFUSE) { size += sizeof(DWORD); elts += 1; }
852 if (d3dvtVertexType & D3DFVF_SPECULAR) { size += sizeof(DWORD); elts += 1; }
Lionel Ulmerc5f38752002-11-30 19:27:19 +0000853 switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
Lionel Ulmer91c6f812002-12-15 01:17:59 +0000854 case D3DFVF_XYZ: size += 3 * sizeof(D3DVALUE); elts += 1; break;
855 case D3DFVF_XYZRHW: size += 4 * sizeof(D3DVALUE); elts += 1; break;
Lionel Ulmerc5f38752002-11-30 19:27:19 +0000856 default: TRACE(" matrix weighting not handled yet...\n");
857 }
858 size += 2 * sizeof(D3DVALUE) * ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
Lionel Ulmer91c6f812002-12-15 01:17:59 +0000859 elts += (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT;
860
861 if (elements) *elements = elts;
Lionel Ulmerc5f38752002-11-30 19:27:19 +0000862
863 return size;
864}
865
866void dump_flexible_vertex(DWORD d3dvtVertexType)
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000867{
868 static const flag_info flags[] = {
869 FE(D3DFVF_NORMAL),
870 FE(D3DFVF_RESERVED1),
871 FE(D3DFVF_DIFFUSE),
872 FE(D3DFVF_SPECULAR)
873 };
874 if (d3dvtVertexType & D3DFVF_RESERVED0) DPRINTF("D3DFVF_RESERVED0 ");
875 switch (d3dvtVertexType & D3DFVF_POSITION_MASK) {
876#define GEN_CASE(a) case a: DPRINTF(#a " "); break
877 GEN_CASE(D3DFVF_XYZ);
878 GEN_CASE(D3DFVF_XYZRHW);
879 GEN_CASE(D3DFVF_XYZB1);
880 GEN_CASE(D3DFVF_XYZB2);
881 GEN_CASE(D3DFVF_XYZB3);
882 GEN_CASE(D3DFVF_XYZB4);
883 GEN_CASE(D3DFVF_XYZB5);
884 }
885 DDRAW_dump_flags_(d3dvtVertexType, flags, sizeof(flags)/sizeof(flags[0]), FALSE);
886 switch (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) {
887 GEN_CASE(D3DFVF_TEX0);
888 GEN_CASE(D3DFVF_TEX1);
889 GEN_CASE(D3DFVF_TEX2);
890 GEN_CASE(D3DFVF_TEX3);
891 GEN_CASE(D3DFVF_TEX4);
892 GEN_CASE(D3DFVF_TEX5);
893 GEN_CASE(D3DFVF_TEX6);
894 GEN_CASE(D3DFVF_TEX7);
895 GEN_CASE(D3DFVF_TEX8);
896 }
897#undef GEN_CASE
898 DPRINTF("\n");
899}
900
901/* Some types used by the fast paths... */
902typedef struct {
903 float x, y, z;
904 float nx, ny, nz;
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000905 float tu1, tv1;
906} D3DFVF_VERTEX_1;
907
Lionel Ulmera6e50802002-11-30 19:19:00 +0000908typedef struct {
909 float x, y, z, rhw;
910 DWORD diffuse;
911 DWORD specular;
912 float tu1, tv1;
913} D3DFVF_TLVERTEX_1;
914
Lionel Ulmer91c6f812002-12-15 01:17:59 +0000915typedef struct {
916 int offset;
917 int extra;
918 void (*handler)(char *vertex, int offset, int extra);
919} D3DFVF_GENERIC;
920
921/* These are the various handler used in the generic path */
922static void handle_xyz(char *vertex, int offset, int extra) {
923 glVertex3fv((float *) (vertex + offset));
924}
925static void handle_xyzrhw(char *vertex, int offset, int extra) {
926 float *coords = (float *) (vertex + offset);
927 if (coords[3] < 0.00001)
928 glVertex3f(coords[0], coords[1], coords[2]);
929 else
930 glVertex4f(coords[0] / coords[3],
931 coords[1] / coords[3],
932 coords[2] / coords[3],
933 1.0 / coords[3]);
934}
935static void handle_normal(char *vertex, int offset, int extra) {
936 glNormal3fv((float *) (vertex + offset));
937}
938static void handle_specular(char *vertex, int offset, int extra) {
939 /* Specular not handled yet properly... */
940}
941static void handle_diffuse(char *vertex, int offset, int extra) {
942 DWORD color = *((DWORD *) (vertex + offset));
943 glColor4ub((color >> 24) & 0xFF,
944 (color >> 16) & 0xFF,
945 (color >> 8) & 0xFF,
946 (color >> 0) & 0xFF);
947}
948static void handle_texture(char *vertex, int offset, int extra) {
949 if (extra == 0xFF) {
950 /* Special case for single texture... */
951 glTexCoord2fv((float *) (vertex + offset));
952 } else {
953 /* Multitexturing not handled yet */
954 }
955}
956
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000957static void draw_primitive_7(IDirect3DDeviceImpl *This,
958 D3DPRIMITIVETYPE d3dptPrimitiveType,
959 DWORD d3dvtVertexType,
960 LPVOID lpvVertices,
961 DWORD dwVertexCount,
962 LPWORD dwIndices,
963 DWORD dwIndexCount,
964 DWORD dwFlags)
965{
Lionel Ulmera6e50802002-11-30 19:19:00 +0000966 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000967 if (TRACE_ON(ddraw)) {
968 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
969 }
970
971 ENTER_GL();
Lionel Ulmera6e50802002-11-30 19:19:00 +0000972 draw_primitive_handle_GL_state(glThis,
973 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
974 (d3dvtVertexType & D3DFVF_NORMAL) == 0);
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000975 draw_primitive_start_GL(d3dptPrimitiveType);
976
977 /* Some fast paths first before the generic case.... */
978 if (d3dvtVertexType == D3DFVF_VERTEX) {
979 D3DFVF_VERTEX_1 *vertices = (D3DFVF_VERTEX_1 *) lpvVertices;
980 int index;
Lionel Ulmer708c4b22002-11-30 19:12:32 +0000981
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000982 for (index = 0; index < dwIndexCount; index++) {
983 int i = (dwIndices == NULL) ? index : dwIndices[index];
984
Lionel Ulmer91c6f812002-12-15 01:17:59 +0000985 glNormal3fv(&(vertices[i].nx));
986 glTexCoord2fv(&(vertices[i].tu1));
987 glVertex3fv(&(vertices[i].x));
Lionel Ulmer708c4b22002-11-30 19:12:32 +0000988 TRACE(" %f %f %f / %f %f %f (%f %f)\n",
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000989 vertices[i].x, vertices[i].y, vertices[i].z,
990 vertices[i].nx, vertices[i].ny, vertices[i].nz,
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000991 vertices[i].tu1, vertices[i].tv1);
992 }
Lionel Ulmera6e50802002-11-30 19:19:00 +0000993 } else if (d3dvtVertexType == D3DFVF_TLVERTEX) {
994 D3DFVF_TLVERTEX_1 *vertices = (D3DFVF_TLVERTEX_1 *) lpvVertices;
995 int index;
996
997 for (index = 0; index < dwIndexCount; index++) {
998 int i = (dwIndices == NULL) ? index : dwIndices[index];
999
1000 glColor4ub((vertices[i].diffuse >> 24) & 0xFF,
1001 (vertices[i].diffuse >> 16) & 0xFF,
1002 (vertices[i].diffuse >> 8) & 0xFF,
1003 (vertices[i].diffuse >> 0) & 0xFF);
1004 /* Todo : handle specular... */
Lionel Ulmer91c6f812002-12-15 01:17:59 +00001005 glTexCoord2fv(&(vertices[i].tu1));
Lionel Ulmera6e50802002-11-30 19:19:00 +00001006 if (vertices[i].rhw < 0.00001)
1007 glVertex3f(vertices[i].x, vertices[i].y, vertices[i].z);
1008 else
1009 glVertex4f(vertices[i].x / vertices[i].rhw,
1010 vertices[i].y / vertices[i].rhw,
1011 vertices[i].z / vertices[i].rhw,
1012 1.0 / vertices[i].rhw);
1013 TRACE(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1014 vertices[i].x, vertices[i].y, vertices[i].z, vertices[i].rhw,
1015 (vertices[i].diffuse >> 24) & 0xFF,
1016 (vertices[i].diffuse >> 16) & 0xFF,
1017 (vertices[i].diffuse >> 8) & 0xFF,
1018 (vertices[i].diffuse >> 0) & 0xFF,
1019 (vertices[i].specular >> 24) & 0xFF,
1020 (vertices[i].specular >> 16) & 0xFF,
1021 (vertices[i].specular >> 8) & 0xFF,
1022 (vertices[i].specular >> 0) & 0xFF,
1023 vertices[i].tu1, vertices[i].tv1);
1024 }
Lionel Ulmer91c6f812002-12-15 01:17:59 +00001025 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1026 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1027 /* This is the 'slow path' but that should support all possible vertex formats out there...
1028 Note that people should write a fast path for all vertex formats out there...
1029 */
1030 DWORD elements;
1031 DWORD size = get_flexible_vertex_size(d3dvtVertexType, &elements);
1032 char *vertices = (char *) lpvVertices;
1033 int index;
1034 int current_offset = 0;
1035 int current_position = 0;
1036 D3DFVF_GENERIC *handler = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, elements * sizeof(D3DFVF_GENERIC));
1037
1038 WARN(" using draw_primitive generic path - for better performance, add a fast path for your vertex case !\n");
1039
1040 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1041 handler[elements - 1].handler = handle_xyz;
1042 handler[elements - 1].offset = current_offset;
1043 current_offset += 3 * sizeof(D3DVALUE);
1044 } else {
1045 handler[elements - 1].handler = handle_xyzrhw;
1046 handler[elements - 1].offset = current_offset;
1047 current_offset += 4 * sizeof(D3DVALUE);
1048 }
1049 if (d3dvtVertexType & D3DFVF_NORMAL) {
1050 handler[current_position].handler = handle_normal;
1051 handler[current_position].offset = current_offset;
1052 current_position += 1;
1053 current_offset += 3 * sizeof(D3DVALUE);
1054 }
1055 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1056 handler[current_position].handler = handle_diffuse;
1057 handler[current_position].offset = current_offset;
1058 current_position += 1;
1059 current_offset += sizeof(DWORD);
1060 }
1061 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1062 handler[current_position].handler = handle_specular;
1063 handler[current_position].offset = current_offset;
1064 current_position += 1;
1065 current_offset += sizeof(DWORD);
1066 }
1067 if (((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT) == 1) {
1068 handler[current_position].handler = handle_texture;
1069 handler[current_position].offset = current_offset;
1070 handler[current_position].extra = 0xFF;
1071 current_position += 1;
1072 current_offset += 2 * sizeof(D3DVALUE);
1073 } else {
1074 int tex_index;
1075 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1076 handler[current_position].handler = handle_texture;
1077 handler[current_position].offset = current_offset;
1078 handler[current_position].extra = tex_index;
1079 current_position += 1;
1080 current_offset += 2 * sizeof(D3DVALUE);
1081 }
1082 }
1083
1084 for (index = 0; index < dwIndexCount; index++) {
1085 int i = (dwIndices == NULL) ? index : dwIndices[index];
1086 int elt;
1087 char *vertex = vertices + (i * size);
1088
1089 for (elt = 0; elt < elements; elt++) {
1090 handler[elt].handler(vertex, handler[elt].offset, handler[elt].extra);
1091 }
1092 }
1093 } else {
1094 ERR(" matrix weighting not handled yet....\n");
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001095 }
1096
1097 glEnd();
1098 LEAVE_GL();
1099 TRACE("End\n");
1100}
1101
1102
1103HRESULT WINAPI
1104GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1105 D3DPRIMITIVETYPE d3dptPrimitiveType,
1106 DWORD d3dvtVertexType,
1107 LPVOID lpvVertices,
1108 DWORD dwVertexCount,
1109 DWORD dwFlags)
1110{
1111 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1112 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1113
1114 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, NULL, dwVertexCount, dwFlags);
1115
1116 return DD_OK;
1117}
1118
1119HRESULT WINAPI
1120GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1121 D3DPRIMITIVETYPE d3dptPrimitiveType,
1122 DWORD d3dvtVertexType,
1123 LPVOID lpvVertices,
1124 DWORD dwVertexCount,
1125 LPWORD dwIndices,
1126 DWORD dwIndexCount,
1127 DWORD dwFlags)
1128{
1129 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1130 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1131
1132 draw_primitive_7(This, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1133
1134 return DD_OK;
1135}
1136
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001137HRESULT WINAPI
1138GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1139 DWORD dwStage,
1140 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1141 DWORD dwState)
1142{
1143 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1144 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1145 GLenum gl_state;
1146
1147 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1148
1149 if (TRACE_ON(ddraw)) {
1150 TRACE(" Stage type is : ");
1151 switch (d3dTexStageStateType) {
1152#define GEN_CASE(a) case a: DPRINTF(#a " "); break
1153 GEN_CASE(D3DTSS_COLOROP);
1154 GEN_CASE(D3DTSS_COLORARG1);
1155 GEN_CASE(D3DTSS_COLORARG2);
1156 GEN_CASE(D3DTSS_ALPHAOP);
1157 GEN_CASE(D3DTSS_ALPHAARG1);
1158 GEN_CASE(D3DTSS_ALPHAARG2);
1159 GEN_CASE(D3DTSS_BUMPENVMAT00);
1160 GEN_CASE(D3DTSS_BUMPENVMAT01);
1161 GEN_CASE(D3DTSS_BUMPENVMAT10);
1162 GEN_CASE(D3DTSS_BUMPENVMAT11);
1163 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1164 GEN_CASE(D3DTSS_ADDRESS);
1165 GEN_CASE(D3DTSS_ADDRESSU);
1166 GEN_CASE(D3DTSS_ADDRESSV);
1167 GEN_CASE(D3DTSS_BORDERCOLOR);
1168 GEN_CASE(D3DTSS_MAGFILTER);
1169 GEN_CASE(D3DTSS_MINFILTER);
1170 GEN_CASE(D3DTSS_MIPFILTER);
1171 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1172 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1173 GEN_CASE(D3DTSS_MAXANISOTROPY);
1174 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1175 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1176 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1177#undef GEN_CASE
1178 default: DPRINTF("UNKNOWN !!!");
1179 }
1180 DPRINTF(" => ");
1181 }
1182
1183 switch (d3dTexStageStateType) {
1184 case D3DTSS_MINFILTER:
1185 switch ((D3DTEXTUREMINFILTER) dwState) {
1186 case D3DTFN_POINT:
1187 if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_POINT\n");
1188 gl_state = GL_NEAREST;
1189 break;
1190 case D3DTFN_LINEAR:
1191 if (TRACE_ON(ddraw)) DPRINTF("D3DTFN_LINEAR\n");
1192 gl_state = GL_LINEAR;
1193 break;
1194 default:
1195 if (TRACE_ON(ddraw)) DPRINTF(" state unhandled.\n");
1196 gl_state = GL_LINEAR;
1197 break;
1198 }
1199 glThis->render_state.min = gl_state;
1200 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_state);
1201 break;
1202
1203 case D3DTSS_MAGFILTER:
1204 switch ((D3DTEXTUREMAGFILTER) dwState) {
1205 case D3DTFG_POINT:
1206 if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_POINT\n");
1207 gl_state = GL_NEAREST;
1208 break;
1209 case D3DTFG_LINEAR:
1210 if (TRACE_ON(ddraw)) DPRINTF("D3DTFG_LINEAR\n");
1211 gl_state = GL_LINEAR;
1212 break;
1213 default:
1214 if (TRACE_ON(ddraw)) DPRINTF(" state unhandled.\n");
1215 gl_state = GL_LINEAR;
1216 break;
1217 }
1218 glThis->render_state.mag = gl_state;
1219 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_state);
1220 break;
1221
1222 default:
1223 if (TRACE_ON(ddraw)) DPRINTF(" unhandled.\n");
1224 }
1225
1226 return DD_OK;
1227}
1228
1229HRESULT WINAPI
1230GL_IDirect3DDeviceImpl_3_SetTexture(LPDIRECT3DDEVICE3 iface,
1231 DWORD dwStage,
1232 LPDIRECT3DTEXTURE2 lpTexture2)
1233{
1234 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
1235
1236 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
1237
1238 if (This->current_texture[dwStage] != NULL) {
1239 /* Seems that this is not right... Need to test in real Windows
1240 IDirect3DTexture2_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirect3DTexture2)); */
1241 }
1242
1243 ENTER_GL();
1244 if (lpTexture2 == NULL) {
1245 TRACE(" disabling 2D texturing.\n");
1246 glBindTexture(GL_TEXTURE_2D, 0);
1247 glDisable(GL_TEXTURE_2D);
1248 } else {
Lionel Ulmer91c6f812002-12-15 01:17:59 +00001249 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirect3DTexture2, lpTexture2);
1250 IDirect3DTextureGLImpl *tex_glimpl = (IDirect3DTextureGLImpl *) tex_impl->tex_private;
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001251
1252 This->current_texture[dwStage] = tex_impl;
Lionel Ulmer91c6f812002-12-15 01:17:59 +00001253 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001254
1255 TRACE(" activating OpenGL texture %d.\n", tex_glimpl->tex_name);
1256
1257 glEnable(GL_TEXTURE_2D);
1258 glBindTexture(GL_TEXTURE_2D, tex_glimpl->tex_name);
1259 }
1260 LEAVE_GL();
1261
1262 return DD_OK;
1263}
1264
Lionel Ulmer5261f032002-12-02 21:39:34 +00001265HRESULT WINAPI
1266GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
1267 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
1268{
1269 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1270 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
1271
1272 fill_opengl_caps_7(lpD3DHELDevDesc);
1273
1274 TRACE(" returning caps : no dump function yet.\n");
1275
1276 return DD_OK;
1277}
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001278
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001279#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1280# define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
1281#else
1282# define XCAST(fun) (void*)
1283#endif
1284
1285ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
1286{
1287 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1288 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
1289 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
1290 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
Lionel Ulmer5261f032002-12-02 21:39:34 +00001291 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001292 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
1293 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
1294 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
1295 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
1296 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
1297 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
1298 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
1299 XCAST(SetTransform) GL_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
1300 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
1301 XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
1302 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
1303 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
1304 XCAST(SetMaterial) Main_IDirect3DDeviceImpl_7_SetMaterial,
1305 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
1306 XCAST(SetLight) Main_IDirect3DDeviceImpl_7_SetLight,
1307 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
1308 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
1309 XCAST(GetRenderState) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
1310 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
1311 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
1312 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001313 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
1314 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001315 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
1316 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
1317 XCAST(DrawPrimitiveStrided) Main_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
1318 XCAST(DrawIndexedPrimitiveStrided) Main_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
1319 XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawPrimitiveVB,
1320 XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_7_DrawIndexedPrimitiveVB,
1321 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
1322 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_GetTexture,
1323 XCAST(SetTexture) Main_IDirect3DDeviceImpl_7_SetTexture,
1324 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001325 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001326 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
1327 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
1328 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
1329 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
1330 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
1331 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
1332 XCAST(LightEnable) Main_IDirect3DDeviceImpl_7_LightEnable,
1333 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
1334 XCAST(SetClipPlane) Main_IDirect3DDeviceImpl_7_SetClipPlane,
1335 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
1336 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
1337};
1338
1339#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1340#undef XCAST
1341#endif
1342
1343
1344#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1345# define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
1346#else
1347# define XCAST(fun) (void*)
1348#endif
1349
1350ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
1351{
1352 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1353 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
1354 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
1355 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
1356 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
1357 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
1358 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
1359 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
1360 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
1361 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
1362 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
1363 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
1364 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
1365 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
1366 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
1367 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
1368 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
1369 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
1370 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
1371 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
1372 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
1373 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
1374 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
1375 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
1376 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
1377 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
1378 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
1379 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
1380 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
1381 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
1382 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
1383 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
1384 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
1385 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
1386 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
1387 XCAST(DrawPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
1388 XCAST(DrawIndexedPrimitiveVB) Main_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
1389 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
1390 XCAST(GetTexture) Main_IDirect3DDeviceImpl_3_GetTexture,
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001391 XCAST(SetTexture) GL_IDirect3DDeviceImpl_3_SetTexture,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001392 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
1393 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
1394 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
1395};
1396
1397#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1398#undef XCAST
1399#endif
1400
1401
1402#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1403# define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
1404#else
1405# define XCAST(fun) (void*)
1406#endif
1407
1408ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
1409{
1410 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1411 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
1412 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
1413 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
1414 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
1415 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_SwapTextureHandles,
1416 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
1417 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
1418 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
1419 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
1420 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
1421 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
1422 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
1423 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
1424 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
1425 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
1426 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
1427 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
1428 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
1429 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
1430 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
1431 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
1432 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
1433 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
1434 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
1435 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
1436 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
1437 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
1438 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
1439 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
1440 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
1441 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
1442 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
1443 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
1444};
1445
1446#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1447#undef XCAST
1448#endif
1449
1450
1451#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1452# define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
1453#else
1454# define XCAST(fun) (void*)
1455#endif
1456
1457ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
1458{
1459 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
1460 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
1461 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
1462 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
1463 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
1464 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
1465 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_1_SwapTextureHandles,
1466 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
1467 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
1468 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
1469 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
1470 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
1471 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
1472 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
1473 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
1474 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
1475 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
1476 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
1477 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
1478 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
1479 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
1480 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
1481 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
1482};
1483
1484#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
1485#undef XCAST
1486#endif
1487
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001488/* TODO for both these functions :
1489 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
1490 by other OpenGL code in D3D
1491 - handle the case where no 'Begin / EndScene' was done between two locks
1492 - handle the rectangles in the unlock too
Lionel Ulmera6e50802002-11-30 19:19:00 +00001493 - handle pitch correctly...
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001494*/
1495static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
1496{
1497 /* First, check if we need to do anything */
1498 if ((This->lastlocktype & DDLOCK_WRITEONLY) == 0) {
1499 GLenum buffer_type;
1500 GLenum prev_read;
1501 RECT loc_rect;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001502
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001503 ENTER_GL();
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001504
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001505 glGetIntegerv(GL_READ_BUFFER, &prev_read);
1506 glFlush();
1507
1508 WARN(" application does a lock on a 3D surface - expect slow downs.\n");
1509 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1510 /* Application wants to lock the front buffer */
1511 glReadBuffer(GL_FRONT);
1512 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1513 /* Application wants to lock the back buffer */
1514 glReadBuffer(GL_BACK);
1515 } else {
1516 WARN(" do not support 3D surface locking for this surface type - trying to use default buffer.\n");
1517 }
1518
1519 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1520 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1521 } else {
1522 WARN(" unsupported pixel format.\n");
1523 LEAVE_GL();
1524 return;
1525 }
1526 if (pRect == NULL) {
1527 loc_rect.top = 0;
1528 loc_rect.left = 0;
1529 loc_rect.bottom = This->surface_desc.dwHeight;
1530 loc_rect.right = This->surface_desc.dwWidth;
1531 } else {
1532 loc_rect = *pRect;
1533 }
1534 glReadPixels(loc_rect.left, loc_rect.top, loc_rect.right, loc_rect.bottom,
1535 GL_RGB, buffer_type, ((char *)This->surface_desc.lpSurface
1536 + loc_rect.top * This->surface_desc.u1.lPitch
1537 + loc_rect.left * GET_BPP(This->surface_desc)));
1538 glReadBuffer(prev_read);
1539 LEAVE_GL();
1540 }
1541}
1542
1543static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
1544{
1545 /* First, check if we need to do anything */
1546 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
1547 GLenum buffer_type;
1548 GLenum prev_draw;
1549
1550 ENTER_GL();
1551
1552 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
1553
1554 WARN(" application does an unlock on a 3D surface - expect slow downs.\n");
1555 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
1556 /* Application wants to lock the front buffer */
1557 glDrawBuffer(GL_FRONT);
1558 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
1559 /* Application wants to lock the back buffer */
1560 glDrawBuffer(GL_BACK);
1561 } else {
Lionel Ulmer708c4b22002-11-30 19:12:32 +00001562 WARN(" do not support 3D surface unlocking for this surface type - trying to use default buffer.\n");
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001563 }
1564
1565 if (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) {
1566 buffer_type = GL_UNSIGNED_SHORT_5_6_5;
1567 } else {
1568 WARN(" unsupported pixel format.\n");
1569 LEAVE_GL();
1570 return;
1571 }
Lionel Ulmera6e50802002-11-30 19:19:00 +00001572 glRasterPos2f(0.0, 0.0);
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001573 glDrawPixels(This->surface_desc.dwWidth, This->surface_desc.dwHeight,
1574 GL_RGB, buffer_type, This->surface_desc.lpSurface);
1575 glDrawBuffer(prev_draw);
1576
1577 LEAVE_GL();
1578 }
1579}
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001580
1581HRESULT
1582d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfaceImpl *surface)
1583{
1584 IDirect3DDeviceImpl *object;
1585 IDirect3DDeviceGLImpl *gl_object;
1586 IDirectDrawSurfaceImpl *surf;
1587 HDC device_context;
1588 XVisualInfo *vis;
1589 int num;
1590 XVisualInfo template;
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001591 GLenum buffer;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001592
1593 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
1594 if (object == NULL) return DDERR_OUTOFMEMORY;
1595
1596 gl_object = (IDirect3DDeviceGLImpl *) object;
1597
1598 object->ref = 1;
1599 object->d3d = d3d;
1600 object->surface = surface;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001601 object->set_context = set_context;
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001602
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001603 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
1604
1605 device_context = GetDC(surface->ddraw_owner->window);
1606 gl_object->display = get_display(device_context);
1607 gl_object->drawable = get_drawable(device_context);
1608 ReleaseDC(surface->ddraw_owner->window,device_context);
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001609
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001610 ENTER_GL();
1611 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
1612 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
1613 if (vis == NULL) {
1614 HeapFree(GetProcessHeap(), 0, object);
1615 ERR("No visual found !\n");
1616 LEAVE_GL();
1617 return DDERR_INVALIDPARAMS;
1618 } else {
1619 TRACE(" visual found\n");
1620 }
1621
1622 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
1623 NULL, GL_TRUE);
1624
1625 if (gl_object->gl_context == NULL) {
1626 HeapFree(GetProcessHeap(), 0, object);
1627 ERR("Error in context creation !\n");
1628 LEAVE_GL();
1629 return DDERR_INVALIDPARAMS;
1630 } else {
1631 TRACE(" context created (%p)\n", gl_object->gl_context);
1632 }
1633
1634 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
1635 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
1636 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001637 surf->aux_ctx = (LPVOID) gl_object->display;
1638 surf->aux_data = (LPVOID) gl_object->drawable;
1639 surf->aux_flip = opengl_flip;
1640 buffer = GL_BACK;
Christian Costab47c14a2002-10-17 01:20:52 +00001641 break;
1642 }
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001643 }
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001644 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
1645 if (surf == NULL) {
1646 TRACE(" no double buffering : drawing on the front buffer\n");
1647 buffer = GL_FRONT;
1648 }
1649
1650 for (surf = surface; surf->prev_attached != NULL; surf = surf->prev_attached) ;
1651 for (; surf != NULL; surf = surf->next_attached) {
1652 if (((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
1653 ((surf->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
1654 /* Override the Lock / Unlock function for all these surfaces */
1655 surf->lock_update = d3ddevice_lock_update;
1656 surf->unlock_update = d3ddevice_unlock_update;
1657 }
1658 surf->d3ddevice = object;
1659 }
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001660
1661 gl_object->render_state.src = GL_ONE;
1662 gl_object->render_state.dst = GL_ZERO;
1663 gl_object->render_state.mag = GL_NEAREST;
1664 gl_object->render_state.min = GL_NEAREST;
Marcus Meissner10ad97c2000-04-09 14:30:50 +00001665
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001666 /* Allocate memory for the matrices */
1667 gl_object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1668 gl_object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1669 gl_object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
1670
1671 memcpy(gl_object->world_mat, id_mat, 16 * sizeof(float));
1672 memcpy(gl_object->view_mat , id_mat, 16 * sizeof(float));
1673 memcpy(gl_object->proj_mat , id_mat, 16 * sizeof(float));
Marcus Meissner10ad97c2000-04-09 14:30:50 +00001674
1675 /* Initialisation */
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001676 TRACE(" setting current context\n");
Christian Costa427b3332002-09-27 22:01:12 +00001677 LEAVE_GL();
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001678 object->set_context(object);
Christian Costa427b3332002-09-27 22:01:12 +00001679 ENTER_GL();
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001680 TRACE(" current context set\n");
Marcus Meissner10ad97c2000-04-09 14:30:50 +00001681 glClearColor(0.0, 0.0, 0.0, 0.0);
1682 glColor3f(1.0, 1.0, 1.0);
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001683 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
1684 glDrawBuffer(buffer);
Lionel Ulmera6e50802002-11-30 19:19:00 +00001685 glReadBuffer(buffer);
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001686 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
Christian Costa427b3332002-09-27 22:01:12 +00001687 LEAVE_GL();
Lionel Ulmera8cc5f52000-07-16 14:40:35 +00001688
Christian Costa774c5f72002-11-24 22:14:40 +00001689 /* fill_device_capabilities(d3d->ddraw); */
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001690
1691 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
1692 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
1693 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
1694 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
Vincent Béron9a624912002-05-31 23:06:46 +00001695
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001696 *obj = object;
1697
1698 TRACE(" creating implementation at %p.\n", *obj);
1699
1700 return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +00001701}