blob: e2e6299315429f50be92187ebc6349bd603b5a50 [file] [log] [blame]
Christian Costa3d6154a2005-09-25 15:18:18 +00001/*
2 * Direct3D Device
3 *
4 * Copyright (c) 1998-2004 Lionel Ulmer
5 * Copyright (c) 2002-2005 Christian Costa
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00006 *
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00007 * This file contains the MESA implementation of all the D3D devices that
8 * Wine supports.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
Marcus Meissner10ad97c2000-04-09 14:30:50 +000024
Marcus Meissner10ad97c2000-04-09 14:30:50 +000025#include "config.h"
Lionel Ulmer1d45ab42003-08-05 18:28:07 +000026#include "wine/port.h"
Francois Gougete5ddd262001-10-14 16:18:52 +000027
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000028#include <stdarg.h>
Francois Gougete5ddd262001-10-14 16:18:52 +000029#include <string.h>
Alexandre Julliard69361e02003-04-22 04:05:08 +000030#include <math.h>
Francois Gougete5ddd262001-10-14 16:18:52 +000031
Dimitrie O. Paun297f3d82003-01-07 20:36:20 +000032#define NONAMELESSUNION
33#define NONAMELESSSTRUCT
Dmitry Timoshkov46256282005-05-27 20:17:35 +000034
Marcus Meissner10ad97c2000-04-09 14:30:50 +000035#include "windef.h"
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000036#include "winbase.h"
Marcus Meissner10ad97c2000-04-09 14:30:50 +000037#include "winerror.h"
Ove Kaaven1f5315c2002-12-05 20:33:07 +000038#include "objbase.h"
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000039#include "wingdi.h"
Marcus Meissner10ad97c2000-04-09 14:30:50 +000040#include "ddraw.h"
41#include "d3d.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000042#include "wine/debug.h"
Lionel Ulmer1d45ab42003-08-05 18:28:07 +000043#include "wine/library.h"
Marcus Meissner10ad97c2000-04-09 14:30:50 +000044
Christian Costab3473bb2005-06-01 19:52:25 +000045#include "d3d_private.h"
Christian Costa69c3e6f2005-06-06 15:51:50 +000046#include "opengl_private.h"
Marcus Meissner10ad97c2000-04-09 14:30:50 +000047
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000048WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
Lionel Ulmera872c782003-05-12 03:09:17 +000049WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
Lionel Ulmer815118a2003-06-16 01:23:58 +000050
Alexandre Julliard69361e02003-04-22 04:05:08 +000051/* x11drv GDI escapes */
52#define X11DRV_ESCAPE 6789
53enum x11drv_escape_codes
54{
55 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
56 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
57 X11DRV_GET_FONT, /* get current X font for a DC */
58};
59
Lionel Ulmer43c3dc42002-11-21 21:04:16 +000060/* They are non-static as they are used by Direct3D in the creation function */
61const GUID IID_D3DDEVICE_OpenGL = {
62 0x31416d44,
63 0x86ae,
64 0x11d2,
65 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
66};
67
Lionel Ulmerc064dcf2003-01-03 21:07:22 +000068const float id_mat[16] = {
Lionel Ulmer43c3dc42002-11-21 21:04:16 +000069 1.0, 0.0, 0.0, 0.0,
70 0.0, 1.0, 0.0, 0.0,
71 0.0, 0.0, 1.0, 0.0,
72 0.0, 0.0, 0.0, 1.0
Lionel Ulmera8cc5f52000-07-16 14:40:35 +000073};
74
Lionel Ulmerd1291ba2003-07-28 19:05:49 +000075/* This is filled at DLL loading time */
76static D3DDEVICEDESC7 opengl_device_caps;
Lionel Ulmer1d45ab42003-08-05 18:28:07 +000077GL_EXTENSIONS_LIST GL_extensions;
Lionel Ulmerd1291ba2003-07-28 19:05:49 +000078
Lionel Ulmerc064dcf2003-01-03 21:07:22 +000079static void draw_primitive_strided(IDirect3DDeviceImpl *This,
80 D3DPRIMITIVETYPE d3dptPrimitiveType,
81 DWORD d3dvtVertexType,
82 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
Lionel Ulmerc064dcf2003-01-03 21:07:22 +000083 DWORD dwVertexCount,
84 LPWORD dwIndices,
85 DWORD dwIndexCount,
86 DWORD dwFlags) ;
Lionel Ulmer8768a6b2002-12-24 00:48:03 +000087
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +000088static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
89
Christian Costa427b3332002-09-27 22:01:12 +000090/* retrieve the X display to use on a given DC */
91inline static Display *get_display( HDC hdc )
92{
93 Display *display;
94 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
95
96 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
97 sizeof(display), (LPSTR)&display )) display = NULL;
98
99 return display;
100}
101
Lionel Ulmere10a0fd2003-06-16 20:22:46 +0000102#define UNLOCK_TEX_SIZE 256
103
104#define DEPTH_RANGE_BIT (0x00000001 << 0)
105#define VIEWPORT_BIT (0x00000001 << 1)
106
107static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, BOOLEAN use_alpha, BOOLEAN *initial) {
108 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
109 DWORD opt_bitmap = 0x00000000;
110
Lionel Ulmer63d9cfc2003-11-18 23:20:25 +0000111 if ((gl_d3d_dev->current_bound_texture[1] != NULL) &&
112 ((d3d_dev->state_block.texture_stage_state[1][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE))) {
Lionel Ulmera1226732003-11-17 20:02:33 +0000113 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
114 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
115 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
116 }
Lionel Ulmer63d9cfc2003-11-18 23:20:25 +0000117 /* Disable multi-texturing for level 1 to disable all others */
Lionel Ulmera1226732003-11-17 20:02:33 +0000118 glDisable(GL_TEXTURE_2D);
119 }
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +0000120 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
121 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
122 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
123 }
Lionel Ulmera1226732003-11-17 20:02:33 +0000124 if ((gl_d3d_dev->current_bound_texture[0] == NULL) ||
125 (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE))
126 glEnable(GL_TEXTURE_2D);
Lionel Ulmere10a0fd2003-06-16 20:22:46 +0000127 if (gl_d3d_dev->unlock_tex == 0) {
128 glGenTextures(1, &gl_d3d_dev->unlock_tex);
129 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
130 *initial = TRUE;
131 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
132 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
133 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
134 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
135 } else {
136 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
Lionel Ulmer08cc0d12003-07-16 23:28:37 +0000137 *initial = FALSE;
Lionel Ulmere10a0fd2003-06-16 20:22:46 +0000138 }
139 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
140 glMatrixMode(GL_TEXTURE);
141 glLoadIdentity();
142 }
143
144 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
145 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
146 d3ddevice_set_ortho(d3d_dev);
147 }
148
149 if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST);
Lionel Ulmere10a0fd2003-06-16 20:22:46 +0000150 glEnable(GL_SCISSOR_TEST);
151 if ((d3d_dev->active_viewport.dvMinZ != 0.0) ||
152 (d3d_dev->active_viewport.dvMaxZ != 1.0)) {
153 glDepthRange(0.0, 1.0);
154 opt_bitmap |= DEPTH_RANGE_BIT;
155 }
156 if ((d3d_dev->active_viewport.dwX != 0) ||
157 (d3d_dev->active_viewport.dwY != 0) ||
158 (d3d_dev->active_viewport.dwWidth != d3d_dev->surface->surface_desc.dwWidth) ||
159 (d3d_dev->active_viewport.dwHeight != d3d_dev->surface->surface_desc.dwHeight)) {
160 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
161 opt_bitmap |= VIEWPORT_BIT;
162 }
163 glScissor(pRect->left, d3d_dev->surface->surface_desc.dwHeight - pRect->bottom,
164 pRect->right - pRect->left, pRect->bottom - pRect->top);
165 if (gl_d3d_dev->lighting != FALSE) glDisable(GL_LIGHTING);
166 if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE);
167 if (use_alpha) {
168 if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST);
Lionel Ulmerb6ddd8c2003-11-11 00:31:16 +0000169 if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
170 glAlphaFunc(GL_NOTEQUAL, 0.0);
Lionel Ulmere10a0fd2003-06-16 20:22:46 +0000171 } else {
172 if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);
173 }
174 if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST);
175 if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND);
176 if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG);
177 if (gl_d3d_dev->current_tex_env != GL_REPLACE)
178 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
Lionel Ulmere10a0fd2003-06-16 20:22:46 +0000179
180 return opt_bitmap;
181}
182
183static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) {
184 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
185
186 /* And restore all the various states modified by this code */
187 if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST);
188 if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING);
189 if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0))
190 glEnable(GL_ALPHA_TEST);
191 else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))
192 glDisable(GL_ALPHA_TEST);
193 if (use_alpha) {
Lionel Ulmerb6ddd8c2003-11-11 00:31:16 +0000194 if ((gl_d3d_dev->current_alpha_test_func != GL_NOTEQUAL) || (gl_d3d_dev->current_alpha_test_ref != 0.0))
195 glAlphaFunc(gl_d3d_dev->current_alpha_test_func, gl_d3d_dev->current_alpha_test_ref);
Lionel Ulmere10a0fd2003-06-16 20:22:46 +0000196 }
197 if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);
198 if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);
199 if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND);
200 if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG);
201 glDisable(GL_SCISSOR_TEST);
Lionel Ulmere10a0fd2003-06-16 20:22:46 +0000202 if (opt_bitmap & DEPTH_RANGE_BIT) {
203 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
204 }
205 if (opt_bitmap & VIEWPORT_BIT) {
206 glViewport(d3d_dev->active_viewport.dwX,
207 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
208 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
209 }
210 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
211 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
212 }
213
Lionel Ulmer63d9cfc2003-11-18 23:20:25 +0000214 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
215 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
216 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
217 }
218 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);
219 /* Note that here we could directly re-bind the previous texture... But it would in some case be a spurious
220 bind if ever the game changes the texture just after.
221
222 So choose 0x00000001 to postpone the binding to the next time we draw something on screen. */
Lionel Ulmere10a0fd2003-06-16 20:22:46 +0000223 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
224 if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);
Lionel Ulmer63d9cfc2003-11-18 23:20:25 +0000225
226 /* And re-enabled if needed texture level 1 */
227 if ((gl_d3d_dev->current_bound_texture[1] != NULL) &&
228 (d3d_dev->state_block.texture_stage_state[1][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
229 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
230 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
231 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
232 }
233 glEnable(GL_TEXTURE_2D);
234 }
Lionel Ulmere10a0fd2003-06-16 20:22:46 +0000235}
Christian Costa427b3332002-09-27 22:01:12 +0000236
237/* retrieve the X drawable to use on a given DC */
238inline static Drawable get_drawable( HDC hdc )
239{
240 Drawable drawable;
241 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
242
243 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
244 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
245
246 return drawable;
247}
248
Lionel Ulmer783b3232003-05-17 18:41:26 +0000249static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
Christian Costab47c14a2002-10-17 01:20:52 +0000250{
Lionel Ulmer783b3232003-05-17 18:41:26 +0000251 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
252 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
Lionel Ulmer8daf96c2003-05-20 04:10:22 +0000253
Lionel Ulmer783b3232003-05-17 18:41:26 +0000254 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
Christian Costab47c14a2002-10-17 01:20:52 +0000255 ENTER_GL();
Lionel Ulmer068fa5d2003-06-04 23:43:29 +0000256 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
257 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_BACK]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK]);
Lionel Ulmer783b3232003-05-17 18:41:26 +0000258 }
Lionel Ulmer068fa5d2003-06-04 23:43:29 +0000259 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
260 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
Lionel Ulmer783b3232003-05-17 18:41:26 +0000261 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
Christian Costab47c14a2002-10-17 01:20:52 +0000262 LEAVE_GL();
Lionel Ulmer8daf96c2003-05-20 04:10:22 +0000263
Christian Costab47c14a2002-10-17 01:20:52 +0000264 return TRUE;
265}
266
267
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000268/*******************************************************************************
269 * OpenGL static functions
270 */
Christian Costa774c5f72002-11-24 22:14:40 +0000271static void set_context(IDirect3DDeviceImpl* This)
272{
273 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
274
Christian Costa774c5f72002-11-24 22:14:40 +0000275 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
Lionel Ulmered883042003-06-04 23:36:48 +0000276 ENTER_GL();
Christian Costa774c5f72002-11-24 22:14:40 +0000277 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
Christian Costa427b3332002-09-27 22:01:12 +0000278 ERR("Error in setting current context (context %p drawable %ld)!\n",
Christian Costa774c5f72002-11-24 22:14:40 +0000279 glThis->gl_context, glThis->drawable);
Christian Costa427b3332002-09-27 22:01:12 +0000280 }
281 LEAVE_GL();
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000282}
283
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000284static void fill_opengl_caps(D3DDEVICEDESC *d1)
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000285{
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000286 d1->dwSize = sizeof(*d1);
Lionel Ulmerd1291ba2003-07-28 19:05:49 +0000287 d1->dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS | D3DDD_BCLIPPING | D3DDD_LIGHTINGCAPS |
288 D3DDD_LINECAPS | D3DDD_TRICAPS | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH |
289 D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000290 d1->dcmColorModel = D3DCOLOR_RGB;
Lionel Ulmerd1291ba2003-07-28 19:05:49 +0000291 d1->dwDevCaps = opengl_device_caps.dwDevCaps;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000292 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
293 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
294 d1->bClipping = TRUE;
295 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
296 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
297 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
Lionel Ulmerd1291ba2003-07-28 19:05:49 +0000298 d1->dlcLightingCaps.dwNumLights = opengl_device_caps.dwMaxActiveLights;
299 d1->dpcLineCaps = opengl_device_caps.dpcLineCaps;
300 d1->dpcTriCaps = opengl_device_caps.dpcTriCaps;
301 d1->dwDeviceRenderBitDepth = opengl_device_caps.dwDeviceRenderBitDepth;
302 d1->dwDeviceZBufferBitDepth = opengl_device_caps.dwDeviceZBufferBitDepth;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000303 d1->dwMaxBufferSize = 0;
304 d1->dwMaxVertexCount = 65536;
Lionel Ulmerd1291ba2003-07-28 19:05:49 +0000305 d1->dwMinTextureWidth = opengl_device_caps.dwMinTextureWidth;
306 d1->dwMinTextureHeight = opengl_device_caps.dwMinTextureHeight;
307 d1->dwMaxTextureWidth = opengl_device_caps.dwMaxTextureWidth;
308 d1->dwMaxTextureHeight = opengl_device_caps.dwMaxTextureHeight;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000309 d1->dwMinStippleWidth = 1;
310 d1->dwMinStippleHeight = 1;
311 d1->dwMaxStippleWidth = 32;
312 d1->dwMaxStippleHeight = 32;
Lionel Ulmerd1291ba2003-07-28 19:05:49 +0000313 d1->dwMaxTextureRepeat = opengl_device_caps.dwMaxTextureRepeat;
314 d1->dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureAspectRatio;
315 d1->dwMaxAnisotropy = opengl_device_caps.dwMaxAnisotropy;
316 d1->dvGuardBandLeft = opengl_device_caps.dvGuardBandLeft;
317 d1->dvGuardBandRight = opengl_device_caps.dvGuardBandRight;
318 d1->dvGuardBandTop = opengl_device_caps.dvGuardBandTop;
319 d1->dvGuardBandBottom = opengl_device_caps.dvGuardBandBottom;
320 d1->dvExtentsAdjust = opengl_device_caps.dvExtentsAdjust;
321 d1->dwStencilCaps = opengl_device_caps.dwStencilCaps;
322 d1->dwFVFCaps = opengl_device_caps.dwFVFCaps;
323 d1->dwTextureOpCaps = opengl_device_caps.dwTextureOpCaps;
324 d1->wMaxTextureBlendStages = opengl_device_caps.wMaxTextureBlendStages;
325 d1->wMaxSimultaneousTextures = opengl_device_caps.wMaxSimultaneousTextures;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000326}
327
Lionel Ulmerf4b941e2002-11-30 19:21:42 +0000328static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
329{
Lionel Ulmerd1291ba2003-07-28 19:05:49 +0000330 *d = opengl_device_caps;
Lionel Ulmerf4b941e2002-11-30 19:21:42 +0000331}
332
Lionel Ulmera872c782003-05-12 03:09:17 +0000333HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000334{
Lionel Ulmerc064dcf2003-01-03 21:07:22 +0000335 D3DDEVICEDESC dref, d1, d2;
Lionel Ulmer00a3d5f2003-01-02 20:13:47 +0000336 HRESULT ret_value;
Christian Costa4ea95892003-05-11 03:28:33 +0000337
338 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
339 Let's put the string in a sufficiently sized array in writable memory. */
340 char device_name[50];
341 strcpy(device_name,"direct3d");
342
Lionel Ulmerc064dcf2003-01-03 21:07:22 +0000343 fill_opengl_caps(&dref);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000344
Lionel Ulmera872c782003-05-12 03:09:17 +0000345 if (version > 1) {
346 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
Daniel Marmier03486492003-10-06 21:03:32 +0000347 char interface_name[] = "WINE Reference Direct3DX using OpenGL";
Lionel Ulmera872c782003-05-12 03:09:17 +0000348 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
349 d1 = dref;
350 d2 = dref;
Daniel Marmier03486492003-10-06 21:03:32 +0000351 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, interface_name, device_name, &d1, &d2, context);
Lionel Ulmera872c782003-05-12 03:09:17 +0000352 if (ret_value != D3DENUMRET_OK)
353 return ret_value;
354 }
Daniel Marmier03486492003-10-06 21:03:32 +0000355
356 {
357 char interface_name[] = "WINE Direct3DX using OpenGL";
358 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
359 d1 = dref;
360 d2 = dref;
361 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, interface_name, device_name, &d1, &d2, context);
362 if (ret_value != D3DENUMRET_OK)
363 return ret_value;
364 }
Lionel Ulmerc064dcf2003-01-03 21:07:22 +0000365
Lionel Ulmer00a3d5f2003-01-02 20:13:47 +0000366 return D3DENUMRET_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000367}
368
Lionel Ulmerf4b941e2002-11-30 19:21:42 +0000369HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
370{
371 D3DDEVICEDESC7 ddesc;
Daniel Marmier03486492003-10-06 21:03:32 +0000372 char interface_name[] = "WINE Direct3D7 using OpenGL";
373 char device_name[] = "Wine D3D7 device";
Lionel Ulmerf4b941e2002-11-30 19:21:42 +0000374
375 fill_opengl_caps_7(&ddesc);
376
377 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
378
Daniel Marmier03486492003-10-06 21:03:32 +0000379 return cb(interface_name, device_name, &ddesc, context);
Lionel Ulmerf4b941e2002-11-30 19:21:42 +0000380}
381
Mike McCormack82f9c972005-08-01 09:22:26 +0000382static ULONG WINAPI
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000383GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
384{
385 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
386 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
Paul Vriens202b3402005-01-09 17:29:21 +0000387 ULONG ref = InterlockedDecrement(&This->ref);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000388
Paul Vriens202b3402005-01-09 17:29:21 +0000389 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, ref + 1);
390
391 if (!ref) {
Lionel Ulmer07f12692003-01-05 01:04:55 +0000392 int i;
Lionel Ulmer783b3232003-05-17 18:41:26 +0000393 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
394
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000395 /* Release texture associated with the device */
Lionel Ulmer11b1b942003-05-20 02:15:24 +0000396 for (i = 0; i < MAX_TEXTURES; i++) {
Lionel Ulmer07f12692003-01-05 01:04:55 +0000397 if (This->current_texture[i] != NULL)
398 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
Lionel Ulmer11b1b942003-05-20 02:15:24 +0000399 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
400 }
Lionel Ulmeree65d592002-12-16 22:57:39 +0000401
Lionel Ulmer783b3232003-05-17 18:41:26 +0000402 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
403 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
404 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
405 surf->aux_ctx = NULL;
406 surf->aux_data = NULL;
407 surf->aux_flip = NULL;
408 break;
409 }
410 }
411 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
412 IDirectDrawSurfaceImpl *surf2;
413 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
414 for (; surf2 != NULL; surf2 = surf2->next_attached) {
415 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
416 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
417 /* Override the Lock / Unlock function for all these surfaces */
418 surf2->lock_update = surf2->lock_update_prev;
Lionel Ulmer2d275042003-05-19 21:37:50 +0000419 surf2->unlock_update = surf2->unlock_update_prev;
Lionel Ulmer783b3232003-05-17 18:41:26 +0000420 /* And install also the blt / bltfast overrides */
421 surf2->aux_blt = NULL;
422 surf2->aux_bltfast = NULL;
423 }
424 surf2->d3ddevice = NULL;
425 }
426 }
Lionel Ulmer449f6b22003-05-11 03:44:53 +0000427
Lionel Ulmer8cd26092003-01-02 19:39:57 +0000428 /* And warn the D3D object that this device is no longer active... */
Lionel Ulmer4aba2822003-06-04 23:31:39 +0000429 This->d3d->d3d_removed_device(This->d3d, This);
Lionel Ulmer8cd26092003-01-02 19:39:57 +0000430
Antoine Chavasseb65e7902005-06-07 21:34:40 +0000431 /* Free light arrays */
Christian Costa3d6154a2005-09-25 15:18:18 +0000432 HeapFree(GetProcessHeap(), 0, This->light_parameters);
Antoine Chavasseb65e7902005-06-07 21:34:40 +0000433 HeapFree(GetProcessHeap(), 0, This->active_lights);
434
Lionel Ulmereb6e8302003-01-02 19:53:43 +0000435 HeapFree(GetProcessHeap(), 0, This->world_mat);
436 HeapFree(GetProcessHeap(), 0, This->view_mat);
437 HeapFree(GetProcessHeap(), 0, This->proj_mat);
438
Christian Costa3d6154a2005-09-25 15:18:18 +0000439 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
Lionel Ulmer97140ba2003-06-04 23:26:53 +0000440
Lionel Ulmer449f6b22003-05-11 03:44:53 +0000441 DeleteCriticalSection(&(This->crit));
442
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000443 ENTER_GL();
Lionel Ulmer783b3232003-05-17 18:41:26 +0000444 if (glThis->unlock_tex)
445 glDeleteTextures(1, &(glThis->unlock_tex));
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000446 glXDestroyContext(glThis->display, glThis->gl_context);
447 LEAVE_GL();
Christoph Frick7f4cb062003-01-07 19:42:26 +0000448 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
Christian Costa3d6154a2005-09-25 15:18:18 +0000449 HeapFree(GetProcessHeap(), 0, This->vertex_buffer);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000450
451 HeapFree(GetProcessHeap(), 0, This);
452 return 0;
453 }
Paul Vriens202b3402005-01-09 17:29:21 +0000454 return ref;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000455}
456
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000457HRESULT WINAPI
458GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
459 LPD3DDEVICEDESC lpD3DHWDevDesc,
460 LPD3DDEVICEDESC lpD3DHELDevDesc)
461{
462 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
463 D3DDEVICEDESC desc;
464 DWORD dwSize;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000465
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000466 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
Vincent BĂ©ron9a624912002-05-31 23:06:46 +0000467
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000468 fill_opengl_caps(&desc);
469 dwSize = lpD3DHWDevDesc->dwSize;
470 memset(lpD3DHWDevDesc, 0, dwSize);
471 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
472
473 dwSize = lpD3DHELDevDesc->dwSize;
474 memset(lpD3DHELDevDesc, 0, dwSize);
475 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
476
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000477 TRACE(" returning caps : (no dump function yet)\n");
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000478
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000479 return DD_OK;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000480}
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000481
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000482static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
483 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
Christian Costae64aae02005-02-14 11:09:46 +0000484 LPVOID context, int version)
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000485{
486 DDSURFACEDESC sdesc;
487 LPDDPIXELFORMAT pformat;
488
489 /* Do the texture enumeration */
490 sdesc.dwSize = sizeof(DDSURFACEDESC);
491 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
492 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
493 pformat = &(sdesc.ddpfPixelFormat);
494 pformat->dwSize = sizeof(DDPIXELFORMAT);
495 pformat->dwFourCC = 0;
496
Lionel Ulmer9914a8e2003-05-08 21:03:57 +0000497 TRACE("Enumerating GL_RGBA unpacked (32)\n");
498 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
499 pformat->u1.dwRGBBitCount = 32;
500 pformat->u2.dwRBitMask = 0x00FF0000;
501 pformat->u3.dwGBitMask = 0x0000FF00;
502 pformat->u4.dwBBitMask = 0x000000FF;
503 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
504 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
505 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000506
Lionel Ulmer449f6b22003-05-11 03:44:53 +0000507 TRACE("Enumerating GL_RGB unpacked (32)\n");
508 pformat->dwFlags = DDPF_RGB;
509 pformat->u1.dwRGBBitCount = 32;
510 pformat->u2.dwRBitMask = 0x00FF0000;
511 pformat->u3.dwGBitMask = 0x0000FF00;
512 pformat->u4.dwBBitMask = 0x000000FF;
513 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
514 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
515 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
Lionel Ulmer449f6b22003-05-11 03:44:53 +0000516
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000517 TRACE("Enumerating GL_RGB unpacked (24)\n");
518 pformat->dwFlags = DDPF_RGB;
519 pformat->u1.dwRGBBitCount = 24;
Lionel Ulmereb6e8302003-01-02 19:53:43 +0000520 pformat->u2.dwRBitMask = 0x00FF0000;
521 pformat->u3.dwGBitMask = 0x0000FF00;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000522 pformat->u4.dwBBitMask = 0x000000FF;
523 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
524 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
525 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000526
Lionel Ulmere51b0072003-01-03 21:09:25 +0000527 /* Note : even if this is an 'emulated' texture format, it needs to be first
528 as some dumb applications seem to rely on that. */
Lionel Ulmerc064dcf2003-01-03 21:07:22 +0000529 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
530 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
531 pformat->u1.dwRGBBitCount = 16;
532 pformat->u2.dwRBitMask = 0x00007C00;
533 pformat->u3.dwGBitMask = 0x000003E0;
534 pformat->u4.dwBBitMask = 0x0000001F;
535 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
536 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
537 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
538
Lionel Ulmera62fc662002-12-17 04:14:55 +0000539 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
540 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
541 pformat->u1.dwRGBBitCount = 16;
542 pformat->u2.dwRBitMask = 0x00000F00;
543 pformat->u3.dwGBitMask = 0x000000F0;
544 pformat->u4.dwBBitMask = 0x0000000F;
545 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
546 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
547 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
548
Lionel Ulmera872c782003-05-12 03:09:17 +0000549 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
550 pformat->dwFlags = DDPF_RGB;
551 pformat->u1.dwRGBBitCount = 16;
552 pformat->u2.dwRBitMask = 0x0000F800;
553 pformat->u3.dwGBitMask = 0x000007E0;
554 pformat->u4.dwBBitMask = 0x0000001F;
555 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
556 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
557 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
558
559 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
560 pformat->dwFlags = DDPF_RGB;
561 pformat->u1.dwRGBBitCount = 16;
562 pformat->u2.dwRBitMask = 0x00007C00;
563 pformat->u3.dwGBitMask = 0x000003E0;
564 pformat->u4.dwBBitMask = 0x0000001F;
565 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
566 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
567 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
568
Lionel Ulmercec93d02003-01-03 21:16:03 +0000569#if 0
570 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
571 find enumerated, others the last one. And both want to have the ARGB one.
572
573 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
574 */
Lionel Ulmer4aba2822003-06-04 23:31:39 +0000575 /* See argument about the RGBA format for 'packed' texture formats */
576 TRACE("Enumerating GL_RGBA unpacked (32)\n");
577 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
578 pformat->u1.dwRGBBitCount = 32;
579 pformat->u2.dwRBitMask = 0xFF000000;
580 pformat->u3.dwGBitMask = 0x00FF0000;
581 pformat->u4.dwBBitMask = 0x0000FF00;
582 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
583 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
584 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
585
Lionel Ulmere51b0072003-01-03 21:09:25 +0000586 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
587 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
588 pformat->u1.dwRGBBitCount = 16;
589 pformat->u2.dwRBitMask = 0x0000F000;
590 pformat->u3.dwGBitMask = 0x00000F00;
591 pformat->u4.dwBBitMask = 0x000000F0;
592 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
593 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
594 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
595
Lionel Ulmercec93d02003-01-03 21:16:03 +0000596 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
597 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
598 pformat->u1.dwRGBBitCount = 16;
599 pformat->u2.dwRBitMask = 0x0000F800;
600 pformat->u3.dwGBitMask = 0x000007C0;
601 pformat->u4.dwBBitMask = 0x0000003E;
602 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
603 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
604 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
605#endif
606
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000607 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
608 pformat->dwFlags = DDPF_RGB;
609 pformat->u1.dwRGBBitCount = 8;
610 pformat->u2.dwRBitMask = 0x000000E0;
611 pformat->u3.dwGBitMask = 0x0000001C;
612 pformat->u4.dwBBitMask = 0x00000003;
613 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
614 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
615 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000616
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000617 TRACE("Enumerating Paletted (8)\n");
618 pformat->dwFlags = DDPF_PALETTEINDEXED8;
619 pformat->u1.dwRGBBitCount = 8;
Lionel Ulmereb6e8302003-01-02 19:53:43 +0000620 pformat->u2.dwRBitMask = 0x00000000;
621 pformat->u3.dwGBitMask = 0x00000000;
622 pformat->u4.dwBBitMask = 0x00000000;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000623 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
624 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
625 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
626
Christian Costae64aae02005-02-14 11:09:46 +0000627 /* DXT textures only exist for devices created from IDirect3D3 and above */
628 if ((version >= 3) && GL_extensions.s3tc_compressed_texture) {
Christian Costaeac96b52004-07-30 18:54:32 +0000629 TRACE("Enumerating DXT1\n");
630 pformat->dwFlags = DDPF_FOURCC;
631 pformat->dwFourCC = MAKE_FOURCC('D','X','T','1');
632 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
633 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
634
635 TRACE("Enumerating DXT3\n");
636 pformat->dwFlags = DDPF_FOURCC;
637 pformat->dwFourCC = MAKE_FOURCC('D','X','T','3');
638 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
639 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
640
641 TRACE("Enumerating DXT5\n");
642 pformat->dwFlags = DDPF_FOURCC;
643 pformat->dwFourCC = MAKE_FOURCC('D','X','T','5');
644 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
645 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
646 }
647
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000648 TRACE("End of enumeration\n");
Vincent BĂ©ron9a624912002-05-31 23:06:46 +0000649 return DD_OK;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000650}
Vincent BĂ©ron9a624912002-05-31 23:06:46 +0000651
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000652
653HRESULT
Lionel Ulmer4aba2822003-06-04 23:31:39 +0000654d3ddevice_find(IDirectDrawImpl *d3d,
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000655 LPD3DFINDDEVICESEARCH lpD3DDFS,
Lionel Ulmerb0350a32002-12-05 19:07:59 +0000656 LPD3DFINDDEVICERESULT lplpD3DDevice)
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000657{
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000658 D3DDEVICEDESC desc;
659
660 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
661 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
662 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
663 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
664 }
665 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
666 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
Lionel Ulmer00a3d5f2003-01-02 20:13:47 +0000667 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
668 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
669 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000670 TRACE(" no match for this GUID.\n");
671 return DDERR_INVALIDPARAMS;
672 }
673 }
674
Lionel Ulmerb0350a32002-12-05 19:07:59 +0000675 /* Now return our own GUID */
676 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000677 fill_opengl_caps(&desc);
Lionel Ulmerc6f5baa2002-12-23 02:03:38 +0000678 lplpD3DDevice->ddHwDesc = desc;
679 lplpD3DDevice->ddSwDesc = desc;
680
681 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
Lionel Ulmer710b86e2002-11-24 22:33:41 +0000682
683 return D3D_OK;
684}
685
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000686HRESULT WINAPI
687GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
688 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
689 LPVOID lpArg)
690{
691 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
692 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
Christian Costae64aae02005-02-14 11:09:46 +0000693 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg, This->version);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000694}
695
Mike McCormack82f9c972005-08-01 09:22:26 +0000696static HRESULT WINAPI
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000697GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
698 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
699 LPVOID lpArg)
700{
701 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
702 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
Christian Costae64aae02005-02-14 11:09:46 +0000703 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg, This->version);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000704}
705
Mike McCormack82f9c972005-08-01 09:22:26 +0000706static HRESULT WINAPI
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000707GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
708 D3DRENDERSTATETYPE dwRenderStateType,
709 DWORD dwRenderState)
710{
711 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000712 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
713
714 /* Call the render state functions */
Lionel Ulmer1213c172003-01-07 23:08:31 +0000715 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
716 set_render_state(This, dwRenderStateType, &This->state_block);
Christian Costa4fc7a842003-01-03 21:08:50 +0000717
718 return DD_OK;
719}
720
Mike McCormack82f9c972005-08-01 09:22:26 +0000721static HRESULT WINAPI
Christian Costa4fc7a842003-01-03 21:08:50 +0000722GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
723 D3DRENDERSTATETYPE dwRenderStateType,
724 LPDWORD lpdwRenderState)
725{
726 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
Christian Costa4fc7a842003-01-03 21:08:50 +0000727 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
728
729 /* Call the render state functions */
Lionel Ulmer1213c172003-01-07 23:08:31 +0000730 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
731
732 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000733
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000734 return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000735}
736
Mike McCormack82f9c972005-08-01 09:22:26 +0000737static HRESULT WINAPI
Christian Costa479c13b2004-08-06 17:30:44 +0000738GL_IDirect3DDeviceImpl_3_2T_GetLightState(LPDIRECT3DDEVICE3 iface,
739 D3DLIGHTSTATETYPE dwLightStateType,
740 LPDWORD lpdwLightState)
741{
742 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
743
744 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwLightStateType, lpdwLightState);
745
746 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX)) {
747 TRACE("Unexpected Light State Type\n");
748 return DDERR_INVALIDPARAMS;
749 }
750
751 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
752 *lpdwLightState = This->material;
753 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
754 *lpdwLightState = D3DCOLOR_RGB;
755 } else {
756 D3DRENDERSTATETYPE rs;
757 switch (dwLightStateType) {
758 case D3DLIGHTSTATE_AMBIENT: /* 2 */
759 rs = D3DRENDERSTATE_AMBIENT;
760 break;
761 case D3DLIGHTSTATE_FOGMODE: /* 4 */
762 rs = D3DRENDERSTATE_FOGVERTEXMODE;
763 break;
764 case D3DLIGHTSTATE_FOGSTART: /* 5 */
765 rs = D3DRENDERSTATE_FOGSTART;
766 break;
767 case D3DLIGHTSTATE_FOGEND: /* 6 */
768 rs = D3DRENDERSTATE_FOGEND;
769 break;
770 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
771 rs = D3DRENDERSTATE_FOGDENSITY;
772 break;
773 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
774 rs = D3DRENDERSTATE_COLORVERTEX;
775 break;
776 default:
777 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType);
778 return DDERR_INVALIDPARAMS;
779 }
780
781 IDirect3DDevice7_GetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
782 rs,lpdwLightState);
783 }
784
785 return DD_OK;
786}
787
Mike McCormack82f9c972005-08-01 09:22:26 +0000788static HRESULT WINAPI
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000789GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
790 D3DLIGHTSTATETYPE dwLightStateType,
791 DWORD dwLightState)
792{
793 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
Christian Costa820b8ca2003-01-20 23:27:08 +0000794
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000795 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
Vincent BĂ©ron9a624912002-05-31 23:06:46 +0000796
Lionel Ulmer4a078c82003-11-09 01:21:25 +0000797 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX)) {
Christian Costa820b8ca2003-01-20 23:27:08 +0000798 TRACE("Unexpected Light State Type\n");
799 return DDERR_INVALIDPARAMS;
Lionel Ulmer4a078c82003-11-09 01:21:25 +0000800 }
Christian Costa820b8ca2003-01-20 23:27:08 +0000801
802 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
803 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000804
Christian Costa820b8ca2003-01-20 23:27:08 +0000805 if (mat != NULL) {
Lionel Ulmer4a078c82003-11-09 01:21:25 +0000806 TRACE(" activating material %p.\n", mat);
Christian Costa820b8ca2003-01-20 23:27:08 +0000807 mat->activate(mat);
Christian Costa820b8ca2003-01-20 23:27:08 +0000808 } else {
Christian Costaa501ea72004-03-23 23:02:37 +0000809 FIXME(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
Christian Costa820b8ca2003-01-20 23:27:08 +0000810 }
Christian Costa479c13b2004-08-06 17:30:44 +0000811 This->material = dwLightState;
Christian Costa820b8ca2003-01-20 23:27:08 +0000812 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
813 switch (dwLightState) {
814 case D3DCOLOR_MONO:
Francois Gougetf803e2a2003-05-13 00:41:57 +0000815 ERR("DDCOLOR_MONO should not happen!\n");
Christian Costa820b8ca2003-01-20 23:27:08 +0000816 break;
817 case D3DCOLOR_RGB:
818 /* We are already in this mode */
Lionel Ulmer4a078c82003-11-09 01:21:25 +0000819 TRACE("Setting color model to RGB (no-op).\n");
Christian Costa820b8ca2003-01-20 23:27:08 +0000820 break;
821 default:
822 ERR("Unknown color model!\n");
Lionel Ulmer4a078c82003-11-09 01:21:25 +0000823 return DDERR_INVALIDPARAMS;
Christian Costa820b8ca2003-01-20 23:27:08 +0000824 }
825 } else {
826 D3DRENDERSTATETYPE rs;
827 switch (dwLightStateType) {
Christian Costa820b8ca2003-01-20 23:27:08 +0000828 case D3DLIGHTSTATE_AMBIENT: /* 2 */
829 rs = D3DRENDERSTATE_AMBIENT;
830 break;
831 case D3DLIGHTSTATE_FOGMODE: /* 4 */
832 rs = D3DRENDERSTATE_FOGVERTEXMODE;
833 break;
834 case D3DLIGHTSTATE_FOGSTART: /* 5 */
835 rs = D3DRENDERSTATE_FOGSTART;
836 break;
837 case D3DLIGHTSTATE_FOGEND: /* 6 */
838 rs = D3DRENDERSTATE_FOGEND;
839 break;
840 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
841 rs = D3DRENDERSTATE_FOGDENSITY;
842 break;
843 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
844 rs = D3DRENDERSTATE_COLORVERTEX;
845 break;
846 default:
Lionel Ulmer4a078c82003-11-09 01:21:25 +0000847 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType);
848 return DDERR_INVALIDPARAMS;
Christian Costa820b8ca2003-01-20 23:27:08 +0000849 }
Marcus Meissner10ad97c2000-04-09 14:30:50 +0000850
Christian Costa820b8ca2003-01-20 23:27:08 +0000851 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
852 rs,dwLightState);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +0000853 }
Christian Costa820b8ca2003-01-20 23:27:08 +0000854
Marcus Meissner3873f442000-04-10 13:45:17 +0000855 return DD_OK;
856}
857
Lionel Ulmer1eaee422003-11-25 00:06:33 +0000858static GLenum convert_D3D_ptype_to_GL(D3DPRIMITIVETYPE d3dpt)
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000859{
860 switch (d3dpt) {
861 case D3DPT_POINTLIST:
Lionel Ulmer1eaee422003-11-25 00:06:33 +0000862 TRACE(" primitive type is POINTS\n");
863 return GL_POINTS;
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000864
865 case D3DPT_LINELIST:
Lionel Ulmer1eaee422003-11-25 00:06:33 +0000866 TRACE(" primitive type is LINES\n");
867 return GL_LINES;
868
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000869 case D3DPT_LINESTRIP:
Lionel Ulmer1eaee422003-11-25 00:06:33 +0000870 TRACE(" primitive type is LINE_STRIP\n");
871 return GL_LINE_STRIP;
872
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000873 case D3DPT_TRIANGLELIST:
Lionel Ulmer1eaee422003-11-25 00:06:33 +0000874 TRACE(" primitive type is TRIANGLES\n");
875 return GL_TRIANGLES;
876
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000877 case D3DPT_TRIANGLESTRIP:
Lionel Ulmer1eaee422003-11-25 00:06:33 +0000878 TRACE(" primitive type is TRIANGLE_STRIP\n");
879 return GL_TRIANGLE_STRIP;
880
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000881 case D3DPT_TRIANGLEFAN:
Lionel Ulmer1eaee422003-11-25 00:06:33 +0000882 TRACE(" primitive type is TRIANGLE_FAN\n");
883 return GL_TRIANGLE_FAN;
884
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000885 default:
Lionel Ulmer16675022003-05-17 18:30:27 +0000886 FIXME("Unhandled primitive %08x\n", d3dpt);
Lionel Ulmer1eaee422003-11-25 00:06:33 +0000887 return GL_POINTS;
Lionel Ulmer5f49e782002-11-30 19:06:52 +0000888 }
889}
890
Christian Costaa49cc9e2003-01-23 01:21:50 +0000891/* This function calculate the Z coordinate from Zproj */
892static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
893{
894 float a,b,c,d;
895 /* Assume that X = Y = 0 and W = 1 */
896 a = This->proj_mat->_33;
897 b = This->proj_mat->_34;
898 c = This->proj_mat->_43;
899 d = This->proj_mat->_44;
900 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
Christian Costaf21887f2003-02-12 01:11:17 +0000901 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
Christian Costaa49cc9e2003-01-23 01:21:50 +0000902 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
903 */
904 return (d*Zproj - c) / (a - b*Zproj);
905}
906
Lionel Ulmer6238f9a2003-02-12 21:26:05 +0000907static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
908 int i;
909
910 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
911
912 for (i = 0; i < 3; i++) {
913 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
914 DWORD elt;
915 for (elt = 0; elt < 0x10000; elt++) {
916 /* We apply the fog transformation and cache the result */
917 DWORD fog_intensity = elt & 0xFF;
918 DWORD vertex_color = (elt >> 8) & 0xFF;
919 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
920 }
921 }
922}
923
Lionel Ulmereb6e8302003-01-02 19:53:43 +0000924static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
Lionel Ulmera6e50802002-11-30 19:19:00 +0000925 BOOLEAN vertex_transformed,
926 BOOLEAN vertex_lit) {
Lionel Ulmereb6e8302003-01-02 19:53:43 +0000927 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
928
Lionel Ulmera6e50802002-11-30 19:19:00 +0000929 /* Puts GL in the correct lighting / transformation mode */
Lionel Ulmer74c3eab2002-12-24 01:07:21 +0000930 if ((vertex_transformed == FALSE) &&
Lionel Ulmer01149452003-01-03 21:05:38 +0000931 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
Lionel Ulmera6e50802002-11-30 19:19:00 +0000932 /* Need to put the correct transformation again if we go from Transformed
933 vertices to non-transformed ones.
934 */
Lionel Ulmer01149452003-01-03 21:05:38 +0000935 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
936 This->world_mat, This->view_mat, This->proj_mat);
937 glThis->transform_state = GL_TRANSFORM_NORMAL;
Lionel Ulmerc3d89f52003-01-02 19:45:23 +0000938
Alexandre Julliardebe3c522004-12-09 14:07:59 +0000939 } else if (vertex_transformed &&
Lionel Ulmer01149452003-01-03 21:05:38 +0000940 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
Lionel Ulmer76beb5b2003-01-05 20:28:35 +0000941 /* Set our orthographic projection */
Lionel Ulmer815118a2003-06-16 01:23:58 +0000942 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
943 glThis->transform_state = GL_TRANSFORM_ORTHO;
944 d3ddevice_set_ortho(This);
945 }
Lionel Ulmera6e50802002-11-30 19:19:00 +0000946 }
Lionel Ulmer4dac4a52003-01-02 20:12:16 +0000947
Lionel Ulmer6238f9a2003-02-12 21:26:05 +0000948 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
Francois Gouget3ca76122003-07-15 20:53:39 +0000949 if no fogging state change occurred */
Alexandre Julliardebe3c522004-12-09 14:07:59 +0000950 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1]) {
951 if (vertex_transformed) {
Lionel Ulmer815118a2003-06-16 01:23:58 +0000952 if (glThis->fogging != 0) {
953 glDisable(GL_FOG);
954 glThis->fogging = 0;
955 }
Lionel Ulmer6238f9a2003-02-12 21:26:05 +0000956 /* Now check if our fog_table still corresponds to the current vertex color.
957 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
958 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
959 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
960 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
961 /* We need to rebuild our fog table.... */
962 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
963 }
964 } else {
965 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
966 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
967 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
968 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
969 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
970 }
971 if (vertex_lit == FALSE) {
972 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
973 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
974 } else {
975 /* Special case of 'pixel fog' */
976 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
977 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
978 }
Lionel Ulmer815118a2003-06-16 01:23:58 +0000979 if (glThis->fogging == 0) {
980 glEnable(GL_FOG);
981 glThis->fogging = 1;
982 }
Lionel Ulmer6238f9a2003-02-12 21:26:05 +0000983 } else {
Lionel Ulmer815118a2003-06-16 01:23:58 +0000984 if (glThis->fogging != 0) {
985 glDisable(GL_FOG);
986 glThis->fogging = 0;
987 }
Lionel Ulmer6238f9a2003-02-12 21:26:05 +0000988 }
989 }
990 } else {
Lionel Ulmer815118a2003-06-16 01:23:58 +0000991 if (glThis->fogging != 0) {
992 glDisable(GL_FOG);
993 glThis->fogging = 0;
994 }
Lionel Ulmer6238f9a2003-02-12 21:26:05 +0000995 }
996
Lionel Ulmer4dac4a52003-01-02 20:12:16 +0000997 /* Handle the 'no-normal' case */
Alexandre Julliardebe3c522004-12-09 14:07:59 +0000998 if ((vertex_lit == FALSE) && This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1]) {
Lionel Ulmer815118a2003-06-16 01:23:58 +0000999 if (glThis->lighting == 0) {
1000 glEnable(GL_LIGHTING);
1001 glThis->lighting = 1;
1002 }
1003 } else {
1004 if (glThis->lighting != 0) {
1005 glDisable(GL_LIGHTING);
1006 glThis->lighting = 0;
1007 }
1008 }
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001009
1010 /* Handle the code for pre-vertex material properties */
1011 if (vertex_transformed == FALSE) {
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001012 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] &&
1013 This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1]) {
Lionel Ulmer1213c172003-01-07 23:08:31 +00001014 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1015 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1016 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
1017 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001018 glEnable(GL_COLOR_MATERIAL);
1019 }
1020 }
Lionel Ulmera6e50802002-11-30 19:19:00 +00001021 }
Lionel Ulmera6e50802002-11-30 19:19:00 +00001022}
1023
1024
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001025inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001026 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
Marcus Meissner10ad97c2000-04-09 14:30:50 +00001027{
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001028 D3DDRAWPRIMITIVESTRIDEDDATA strided;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001029
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001030 switch (d3dvt) {
1031 case D3DVT_VERTEX: {
1032 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1033 strided.position.dwStride = sizeof(D3DVERTEX);
1034 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1035 strided.normal.dwStride = sizeof(D3DVERTEX);
1036 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1037 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
Lionel Ulmer19e6bf92003-02-12 21:40:25 +00001038 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001039 } break;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001040
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001041 case D3DVT_LVERTEX: {
1042 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1043 strided.position.dwStride = sizeof(D3DLVERTEX);
1044 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1045 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1046 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1047 strided.specular.dwStride = sizeof(D3DLVERTEX);
1048 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1049 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
Lionel Ulmer19e6bf92003-02-12 21:40:25 +00001050 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001051 } break;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001052
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001053 case D3DVT_TLVERTEX: {
1054 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1055 strided.position.dwStride = sizeof(D3DTLVERTEX);
1056 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1057 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1058 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1059 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1060 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1061 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
Lionel Ulmer19e6bf92003-02-12 21:40:25 +00001062 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001063 } break;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001064
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001065 default:
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001066 FIXME("Unhandled vertex type %08x\n", d3dvt);
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001067 break;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001068 }
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001069}
1070
1071HRESULT WINAPI
1072GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1073 D3DPRIMITIVETYPE d3dptPrimitiveType,
1074 D3DVERTEXTYPE d3dvtVertexType,
1075 LPVOID lpvVertices,
1076 DWORD dwVertexCount,
1077 DWORD dwFlags)
1078{
1079 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001080
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001081 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1082 if (TRACE_ON(ddraw)) {
1083 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1084 }
1085
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001086 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001087
1088 return DD_OK;
1089}
Christian Costab47c14a2002-10-17 01:20:52 +00001090
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001091HRESULT WINAPI
1092GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1093 D3DPRIMITIVETYPE d3dptPrimitiveType,
1094 D3DVERTEXTYPE d3dvtVertexType,
1095 LPVOID lpvVertices,
1096 DWORD dwVertexCount,
1097 LPWORD dwIndices,
1098 DWORD dwIndexCount,
1099 DWORD dwFlags)
1100{
1101 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1102 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001103 if (TRACE_ON(ddraw)) {
1104 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1105 }
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001106
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001107 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00001108
1109 return DD_OK;
1110}
1111
1112HRESULT WINAPI
1113GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1114 LPD3DEXECUTEBUFFERDESC lpDesc,
1115 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1116 IUnknown* pUnkOuter)
1117{
1118 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1119 IDirect3DExecuteBufferImpl *ret;
1120 HRESULT ret_value;
1121
1122 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1123
1124 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1125 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1126
1127 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1128
1129 return ret_value;
1130}
1131
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00001132static void flush_zbuffer_to_GL(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
1133 static BOOLEAN first = TRUE;
1134 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
Hans Leidekkerfe442b22004-09-08 01:23:57 +00001135 unsigned int row;
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00001136 GLenum type;
1137
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001138 if (first) {
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00001139 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1140 first = FALSE;
1141 }
1142
1143 TRACE("flushing ZBuffer back to GL\n");
1144
1145 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
1146 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
1147 d3ddevice_set_ortho(d3d_dev);
1148 }
1149
1150 glMatrixMode(GL_MODELVIEW);
1151 glLoadIdentity();
1152
1153 if (gl_d3d_dev->depth_test == 0) glEnable(GL_DEPTH_TEST);
1154 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) glDepthFunc(GL_ALWAYS);
1155 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1156
1157 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1158 in some drivers...
1159 */
1160 switch (surf->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth) {
1161 case 16: type = GL_UNSIGNED_SHORT; break;
1162 case 32: type = GL_UNSIGNED_INT; break;
1163 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state;
1164 }
1165
1166 for (row = 0; row < surf->surface_desc.dwHeight; row++) {
1167 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1168 glRasterPos2i(0, row + 1);
1169 glDrawPixels(surf->surface_desc.dwWidth, 1, GL_DEPTH_COMPONENT, type,
1170 ((unsigned char *) surf->surface_desc.lpSurface) + (row * surf->surface_desc.u1.lPitch));
1171 }
1172
1173 restore_state:
1174 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1175 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS)
1176 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1]));
1177 if (gl_d3d_dev->depth_test == 0) glDisable(GL_DEPTH_TEST);
1178}
1179
Lionel Ulmer91c6f812002-12-15 01:17:59 +00001180/* These are the various handler used in the generic path */
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001181inline static void handle_xyz(D3DVALUE *coords) {
Christian Costa3da729e2002-12-24 00:25:39 +00001182 glVertex3fv(coords);
Lionel Ulmer91c6f812002-12-15 01:17:59 +00001183}
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001184inline static void handle_xyzrhw(D3DVALUE *coords) {
Christian Costa479c13b2004-08-06 17:30:44 +00001185 if ((coords[3] < 1e-8) && (coords[3] > -1e-8))
Lionel Ulmer74c3eab2002-12-24 01:07:21 +00001186 glVertex3fv(coords);
1187 else {
1188 GLfloat w = 1.0 / coords[3];
1189
1190 glVertex4f(coords[0] * w,
1191 coords[1] * w,
1192 coords[2] * w,
1193 w);
1194 }
Lionel Ulmer91c6f812002-12-15 01:17:59 +00001195}
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001196inline static void handle_normal(D3DVALUE *coords) {
Christian Costa3da729e2002-12-24 00:25:39 +00001197 glNormal3fv(coords);
Lionel Ulmer91c6f812002-12-15 01:17:59 +00001198}
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001199
Lionel Ulmer1213c172003-01-07 23:08:31 +00001200inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001201 if (sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] ||
1202 sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1]) {
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001203 glColor4ub((*color >> 16) & 0xFF,
1204 (*color >> 8) & 0xFF,
1205 (*color >> 0) & 0xFF,
1206 (*color >> 24) & 0xFF);
1207 } else {
1208 glColor3ub((*color >> 16) & 0xFF,
1209 (*color >> 8) & 0xFF,
1210 (*color >> 0) & 0xFF);
1211 }
Lionel Ulmer91c6f812002-12-15 01:17:59 +00001212}
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001213
Lionel Ulmer1213c172003-01-07 23:08:31 +00001214inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001215 glColor4ub((*color >> 16) & 0xFF,
1216 (*color >> 8) & 0xFF,
1217 (*color >> 0) & 0xFF,
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001218 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
Lionel Ulmer91c6f812002-12-15 01:17:59 +00001219}
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001220
Lionel Ulmer1213c172003-01-07 23:08:31 +00001221inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1222 if ((lighted == FALSE) &&
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001223 sb->render_state[D3DRENDERSTATE_LIGHTING - 1] &&
1224 sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1]) {
Lionel Ulmer1213c172003-01-07 23:08:31 +00001225 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001226 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
Lionel Ulmer1213c172003-01-07 23:08:31 +00001227 handle_diffuse_base(sb, color);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001228 }
Lionel Ulmer1213c172003-01-07 23:08:31 +00001229 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001230 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
Lionel Ulmer1213c172003-01-07 23:08:31 +00001231 handle_diffuse_base(sb, color);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001232 }
Lionel Ulmer1213c172003-01-07 23:08:31 +00001233 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001234 sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1]) {
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001235 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
Lionel Ulmer1213c172003-01-07 23:08:31 +00001236 handle_diffuse_base(sb, color);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001237 }
Lionel Ulmer1213c172003-01-07 23:08:31 +00001238 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001239 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
Lionel Ulmer1213c172003-01-07 23:08:31 +00001240 handle_diffuse_base(sb, color);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001241 }
1242 } else {
Lionel Ulmer1213c172003-01-07 23:08:31 +00001243 handle_diffuse_base(sb, color);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001244 }
Lionel Ulmerc3d89f52003-01-02 19:45:23 +00001245}
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001246
Lionel Ulmer1213c172003-01-07 23:08:31 +00001247inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1248 if ((lighted == FALSE) &&
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001249 sb->render_state[D3DRENDERSTATE_LIGHTING - 1] &&
1250 sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1]) {
Lionel Ulmer1213c172003-01-07 23:08:31 +00001251 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001252 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
Lionel Ulmer1213c172003-01-07 23:08:31 +00001253 handle_specular_base(sb, color);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001254 }
Lionel Ulmer1213c172003-01-07 23:08:31 +00001255 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001256 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
Lionel Ulmer1213c172003-01-07 23:08:31 +00001257 handle_specular_base(sb, color);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001258 }
Lionel Ulmer1213c172003-01-07 23:08:31 +00001259 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001260 sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1]) {
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001261 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
Lionel Ulmer1213c172003-01-07 23:08:31 +00001262 handle_specular_base(sb, color);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001263 }
Lionel Ulmer1213c172003-01-07 23:08:31 +00001264 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001265 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
Lionel Ulmer1213c172003-01-07 23:08:31 +00001266 handle_specular_base(sb, color);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001267 }
1268 }
1269 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
Lionel Ulmerc3d89f52003-01-02 19:45:23 +00001270}
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001271
Lionel Ulmer6238f9a2003-02-12 21:26:05 +00001272inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001273 if (lighted) {
Lionel Ulmer6238f9a2003-02-12 21:26:05 +00001274 DWORD color = *color_d;
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001275 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1]) {
Lionel Ulmer6238f9a2003-02-12 21:26:05 +00001276 /* Special case where the specular value is used to do fogging */
1277 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1278 color &= 0xFF000000; /* Only keep the alpha component */
1279 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1280 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1281 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001282 }
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001283 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1]) {
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001284 /* Standard specular value in transformed mode. TODO */
1285 }
Lionel Ulmer6238f9a2003-02-12 21:26:05 +00001286 handle_diffuse_base(sb, &color);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001287 } else {
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001288 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1]) {
Lionel Ulmer1213c172003-01-07 23:08:31 +00001289 handle_diffuse(sb, color_d, FALSE);
1290 handle_specular(sb, color_s, FALSE);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001291 } else {
1292 /* In that case, only put the diffuse color... */
Lionel Ulmer1213c172003-01-07 23:08:31 +00001293 handle_diffuse_base(sb, color_d);
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001294 }
1295 }
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001296}
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001297
Lionel Ulmer78e95192005-06-12 10:43:11 +00001298static void handle_texture(DWORD size, const D3DVALUE *coords) {
1299 switch (size) {
1300 case 1: glTexCoord1fv(coords); break;
1301 case 2: glTexCoord2fv(coords); break;
1302 case 3: glTexCoord3fv(coords); break;
1303 case 4: glTexCoord4fv(coords); break;
1304 }
Lionel Ulmer8768a6b2002-12-24 00:48:03 +00001305}
Lionel Ulmer78e95192005-06-12 10:43:11 +00001306
1307inline static void handle_textures(DWORD size, const D3DVALUE *coords, int tex_stage) {
1308 if (GL_extensions.max_texture_units > 0) {
1309 GL_extensions.glMultiTexCoord[size - 1](GL_TEXTURE0_WINE + tex_stage, coords);
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00001310 } else {
Lionel Ulmer78e95192005-06-12 10:43:11 +00001311 if (tex_stage == 0) handle_texture(size, coords);
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00001312 }
Lionel Ulmer91c6f812002-12-15 01:17:59 +00001313}
1314
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001315static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1316 D3DPRIMITIVETYPE d3dptPrimitiveType,
1317 DWORD d3dvtVertexType,
1318 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001319 DWORD dwVertexCount,
1320 LPWORD dwIndices,
1321 DWORD dwIndexCount,
1322 DWORD dwFlags)
Christian Costa47b6b942002-12-16 23:07:41 +00001323{
Lionel Ulmerb307e6a2003-02-12 21:36:56 +00001324 BOOLEAN vertex_lighted = FALSE;
Lionel Ulmer6238f9a2003-02-12 21:26:05 +00001325 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
Lionel Ulmera872c782003-05-12 03:09:17 +00001326 int num_active_stages = 0;
Lionel Ulmer78e95192005-06-12 10:43:11 +00001327 int num_tex_index = GET_TEXCOUNT_FROM_FVF(d3dvtVertexType);
Christian Costa85155cc2005-10-12 21:05:40 +00001328 BOOL reenable_depth_test = FALSE;
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001329
Lionel Ulmered883042003-06-04 23:36:48 +00001330 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1331 if (TRACE_ON(ddraw)) {
1332 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1333 }
1334
Lionel Ulmer8352f1f2003-06-04 23:18:24 +00001335 /* This is to prevent 'thread contention' between a thread locking the device and another
1336 doing 3D display on it... */
1337 EnterCriticalSection(&(This->crit));
1338
Lionel Ulmer783b3232003-05-17 18:41:26 +00001339 ENTER_GL();
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00001340 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1341 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
Lionel Ulmer783b3232003-05-17 18:41:26 +00001342 }
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00001343 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00001344
1345 if (This->current_zbuffer == NULL) {
1346 /* Search for an attached ZBuffer */
1347 static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
1348 LPDIRECTDRAWSURFACE7 zbuf;
1349 HRESULT hr;
1350
1351 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7),
1352 (DDSCAPS2 *) &zbuf_caps, &zbuf);
Christian Costa85155cc2005-10-12 21:05:40 +00001353 if (SUCCEEDED(hr)) {
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00001354 This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf);
1355 IDirectDrawSurface7_Release(zbuf);
Christian Costa85155cc2005-10-12 21:05:40 +00001356 } else if (glThis->depth_test) {
1357 glDisable(GL_DEPTH_TEST);
1358 reenable_depth_test = TRUE;
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00001359 }
1360 }
1361 if (This->current_zbuffer != NULL) {
1362 if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) {
1363 flush_zbuffer_to_GL(This, NULL, This->current_zbuffer);
1364 }
1365 }
Lionel Ulmer783b3232003-05-17 18:41:26 +00001366
Christian Costa0accace2003-09-30 00:29:11 +00001367 if ( ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) ||
1368 ((d3dvtVertexType & D3DFVF_NORMAL) == 0) )
Lionel Ulmerb307e6a2003-02-12 21:36:56 +00001369 vertex_lighted = TRUE;
Lionel Ulmerb307e6a2003-02-12 21:36:56 +00001370
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00001371 /* Compute the number of active texture stages and set the various texture parameters */
1372 num_active_stages = draw_primitive_handle_textures(This);
1373
Lionel Ulmer63d9cfc2003-11-18 23:20:25 +00001374 /* And restore to handle '0' in the case we use glTexCoord calls */
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00001375 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1376 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1377 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1378 }
1379
Lionel Ulmereb6e8302003-01-02 19:53:43 +00001380 draw_primitive_handle_GL_state(This,
Christian Costa47b6b942002-12-16 23:07:41 +00001381 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
Lionel Ulmer1213c172003-01-07 23:08:31 +00001382 vertex_lighted);
Christian Costa47b6b942002-12-16 23:07:41 +00001383
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001384 /* First, see if we can use the OpenGL vertex arrays... This is very limited
1385 for now to some 'special' cases where we can do a direct mapping between D3D
1386 types and GL types.
1387
Lionel Ulmer88b928f2003-12-08 21:53:40 +00001388 Note: in the future all calls will go through vertex arrays but the arrays
1389 will be generated by this function.
1390
1391 Note2: colours cannot be mapped directly because they are stored as BGRA in memory
1392 (ie not as an array of R, G, B, A as OpenGL does it but as a LWORD 0xAARRGGBB
1393 which, as we are little indian, gives a B, G, R, A storage in memory.
1394 */
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001395 if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) && /* Standard XYZ vertices */
Lionel Ulmer88b928f2003-12-08 21:53:40 +00001396 ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == 0)) {
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001397 int tex_stage;
1398 TRACE(" using GL vertex arrays for performance !\n");
1399 /* First, the vertices (we are sure we have some :-) */
1400 glEnableClientState(GL_VERTEX_ARRAY);
1401 glVertexPointer(3, GL_FLOAT, lpD3DDrawPrimStrideData->position.dwStride, lpD3DDrawPrimStrideData->position.lpvData);
1402 /* Then the normals */
1403 if (d3dvtVertexType & D3DFVF_NORMAL) {
1404 glEnableClientState(GL_NORMAL_ARRAY);
1405 glNormalPointer(GL_FLOAT, lpD3DDrawPrimStrideData->normal.dwStride, lpD3DDrawPrimStrideData->normal.lpvData);
Christian Costa47b6b942002-12-16 23:07:41 +00001406 }
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001407 /* Then the diffuse colour */
1408 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1409 glEnableClientState(GL_COLOR_ARRAY);
1410 glColorPointer(3, GL_UNSIGNED_BYTE, lpD3DDrawPrimStrideData->normal.dwStride,
1411 ((char *) lpD3DDrawPrimStrideData->diffuse.lpvData));
1412 }
1413 /* Then the various textures */
1414 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1415 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1416 if (tex_index >= num_tex_index) {
1417 WARN("Default texture coordinate not handled in the vertex array path !!!\n");
1418 tex_index = num_tex_index - 1;
Christian Costa3da729e2002-12-24 00:25:39 +00001419 }
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001420 if (GL_extensions.glClientActiveTexture) {
1421 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
Christian Costa3da729e2002-12-24 00:25:39 +00001422 }
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001423 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
Lionel Ulmer78e95192005-06-12 10:43:11 +00001424 glTexCoordPointer(GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index), GL_FLOAT, lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride,
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001425 lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData);
1426 }
1427 if (dwIndices != NULL) {
1428 glDrawElements(convert_D3D_ptype_to_GL(d3dptPrimitiveType), dwIndexCount, GL_UNSIGNED_SHORT, dwIndices);
1429 } else {
1430 glDrawArrays(convert_D3D_ptype_to_GL(d3dptPrimitiveType), 0, dwIndexCount);
1431 }
1432 glDisableClientState(GL_VERTEX_ARRAY);
1433 if (d3dvtVertexType & D3DFVF_NORMAL) {
1434 glDisableClientState(GL_NORMAL_ARRAY);
1435 }
1436 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1437 glDisableClientState(GL_COLOR_ARRAY);
1438 }
1439 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1440 if (GL_extensions.glClientActiveTexture) {
1441 GL_extensions.glClientActiveTexture(GL_TEXTURE0_WINE + tex_stage);
Christian Costa3da729e2002-12-24 00:25:39 +00001442 }
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001443 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
Christian Costa3da729e2002-12-24 00:25:39 +00001444 }
1445 } else {
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001446 glBegin(convert_D3D_ptype_to_GL(d3dptPrimitiveType));
1447
1448 /* Some fast paths first before the generic case.... */
1449 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
Hans Leidekkerfe442b22004-09-08 01:23:57 +00001450 unsigned int index;
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001451
1452 for (index = 0; index < dwIndexCount; index++) {
1453 int i = (dwIndices == NULL) ? index : dwIndices[index];
1454 D3DVALUE *normal =
1455 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1456 D3DVALUE *tex_coord =
1457 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1458 D3DVALUE *position =
1459 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1460
1461 handle_normal(normal);
Lionel Ulmer78e95192005-06-12 10:43:11 +00001462 handle_texture(2, tex_coord);
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001463 handle_xyz(position);
1464
1465 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1466 position[0], position[1], position[2],
1467 normal[0], normal[1], normal[2],
1468 tex_coord[0], tex_coord[1]);
1469 }
1470 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
Hans Leidekkerfe442b22004-09-08 01:23:57 +00001471 unsigned int index;
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001472
1473 for (index = 0; index < dwIndexCount; index++) {
1474 int i = (dwIndices == NULL) ? index : dwIndices[index];
1475 DWORD *color_d =
1476 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1477 DWORD *color_s =
1478 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1479 D3DVALUE *tex_coord =
1480 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1481 D3DVALUE *position =
1482 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1483
1484 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
Lionel Ulmer78e95192005-06-12 10:43:11 +00001485 handle_texture(2, tex_coord);
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001486 handle_xyzrhw(position);
1487
1488 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1489 position[0], position[1], position[2], position[3],
1490 (*color_d >> 16) & 0xFF,
1491 (*color_d >> 8) & 0xFF,
1492 (*color_d >> 0) & 0xFF,
1493 (*color_d >> 24) & 0xFF,
1494 (*color_s >> 16) & 0xFF,
1495 (*color_s >> 8) & 0xFF,
1496 (*color_s >> 0) & 0xFF,
1497 (*color_s >> 24) & 0xFF,
1498 tex_coord[0], tex_coord[1]);
1499 }
1500 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1501 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1502 /* This is the 'slow path' but that should support all possible vertex formats out there...
1503 Note that people should write a fast path for all vertex formats out there...
1504 */
Hans Leidekkerfe442b22004-09-08 01:23:57 +00001505 unsigned int index;
Lionel Ulmer78e95192005-06-12 10:43:11 +00001506 /* static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 }; */
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001507
1508 for (index = 0; index < dwIndexCount; index++) {
1509 int i = (dwIndices == NULL) ? index : dwIndices[index];
1510 int tex_stage;
1511
1512 if (d3dvtVertexType & D3DFVF_NORMAL) {
1513 D3DVALUE *normal =
1514 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1515 handle_normal(normal);
1516 }
1517 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1518 DWORD *color_d =
1519 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1520 DWORD *color_s =
1521 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1522 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1523 } else {
1524 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1525 DWORD *color_s =
1526 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1527 handle_specular(&(This->state_block), color_s, vertex_lighted);
1528 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1529 DWORD *color_d =
1530 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1531 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1532 }
1533 }
1534
1535 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1536 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
Lionel Ulmer78e95192005-06-12 10:43:11 +00001537 D3DVALUE *tex_coord;
1538
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001539 if (tex_index >= num_tex_index) {
Lionel Ulmer78e95192005-06-12 10:43:11 +00001540 /* This will have to be checked on Windows. RealMYST uses this feature and I would find it more
1541 * logical to re-use the index of the previous stage than a default index of '0'.
1542 */
1543
1544 /* handle_textures((const D3DVALUE *) no_index, tex_stage); */
1545 tex_index = num_tex_index - 1;
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001546 }
Lionel Ulmer78e95192005-06-12 10:43:11 +00001547 tex_coord = (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1548 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1549 handle_textures(GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index), tex_coord, tex_stage);
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001550 }
1551
1552 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1553 D3DVALUE *position =
1554 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1555 handle_xyz(position);
1556 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1557 D3DVALUE *position =
1558 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1559 handle_xyzrhw(position);
1560 }
1561
1562 if (TRACE_ON(ddraw_geom)) {
Hans Leidekkerfe442b22004-09-08 01:23:57 +00001563 unsigned int tex_index;
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001564
1565 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1566 D3DVALUE *position =
1567 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1568 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1569 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1570 D3DVALUE *position =
1571 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1572 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1573 }
1574 if (d3dvtVertexType & D3DFVF_NORMAL) {
1575 D3DVALUE *normal =
1576 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1577 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1578 }
1579 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1580 DWORD *color_d =
1581 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1582 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1583 (*color_d >> 16) & 0xFF,
1584 (*color_d >> 8) & 0xFF,
1585 (*color_d >> 0) & 0xFF,
1586 (*color_d >> 24) & 0xFF);
1587 }
1588 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1589 DWORD *color_s =
1590 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1591 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1592 (*color_s >> 16) & 0xFF,
1593 (*color_s >> 8) & 0xFF,
1594 (*color_s >> 0) & 0xFF,
1595 (*color_s >> 24) & 0xFF);
1596 }
Lionel Ulmer78e95192005-06-12 10:43:11 +00001597 for (tex_index = 0; tex_index < GET_TEXCOUNT_FROM_FVF(d3dvtVertexType); tex_index++) {
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001598 D3DVALUE *tex_coord =
1599 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1600 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
Lionel Ulmer78e95192005-06-12 10:43:11 +00001601 switch (GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index)) {
1602 case 1: TRACE_(ddraw_geom)(" / %f", tex_coord[0]); break;
1603 case 2: TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]); break;
1604 case 3: TRACE_(ddraw_geom)(" / %f %f %f", tex_coord[0], tex_coord[1], tex_coord[2]); break;
1605 case 4: TRACE_(ddraw_geom)(" / %f %f %f %f", tex_coord[0], tex_coord[1], tex_coord[2], tex_coord[3]); break;
1606 default: TRACE_(ddraw_geom)("Invalid texture size (%ld) !!!", GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_index)); break;
1607 }
Lionel Ulmer1eaee422003-11-25 00:06:33 +00001608 }
1609 TRACE_(ddraw_geom)("\n");
1610 }
1611 }
1612 } else {
1613 ERR(" matrix weighting not handled yet....\n");
1614 }
1615
1616 glEnd();
Christian Costa47b6b942002-12-16 23:07:41 +00001617 }
Lionel Ulmer4dac4a52003-01-02 20:12:16 +00001618
1619 /* Whatever the case, disable the color material stuff */
1620 glDisable(GL_COLOR_MATERIAL);
1621
Christian Costa85155cc2005-10-12 21:05:40 +00001622 if (reenable_depth_test)
1623 glEnable(GL_DEPTH_TEST);
1624
Christian Costa47b6b942002-12-16 23:07:41 +00001625 LEAVE_GL();
1626 TRACE("End\n");
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001627
1628 LeaveCriticalSection(&(This->crit));
Christian Costa47b6b942002-12-16 23:07:41 +00001629}
1630
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001631HRESULT WINAPI
1632GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1633 D3DPRIMITIVETYPE d3dptPrimitiveType,
1634 DWORD d3dvtVertexType,
1635 LPVOID lpvVertices,
1636 DWORD dwVertexCount,
1637 DWORD dwFlags)
1638{
1639 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001640 D3DDRAWPRIMITIVESTRIDEDDATA strided;
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001641
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001642 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001643 if (TRACE_ON(ddraw)) {
1644 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1645 }
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001646
Lionel Ulmer19e6bf92003-02-12 21:40:25 +00001647 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1648 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001649
1650 return DD_OK;
1651}
1652
1653HRESULT WINAPI
1654GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1655 D3DPRIMITIVETYPE d3dptPrimitiveType,
1656 DWORD d3dvtVertexType,
1657 LPVOID lpvVertices,
1658 DWORD dwVertexCount,
1659 LPWORD dwIndices,
1660 DWORD dwIndexCount,
1661 DWORD dwFlags)
1662{
1663 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001664 D3DDRAWPRIMITIVESTRIDEDDATA strided;
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001665
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001666 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001667 if (TRACE_ON(ddraw)) {
1668 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1669 }
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001670
Lionel Ulmer19e6bf92003-02-12 21:40:25 +00001671 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1672 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
Lionel Ulmer5f49e782002-11-30 19:06:52 +00001673
1674 return DD_OK;
1675}
1676
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001677HRESULT WINAPI
Christian Costa47b6b942002-12-16 23:07:41 +00001678GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1679 D3DPRIMITIVETYPE d3dptPrimitiveType,
1680 DWORD dwVertexType,
1681 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1682 DWORD dwVertexCount,
1683 DWORD dwFlags)
1684{
1685 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001686
Christian Costa47b6b942002-12-16 23:07:41 +00001687 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001688 if (TRACE_ON(ddraw)) {
1689 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1690 }
Lionel Ulmer19e6bf92003-02-12 21:40:25 +00001691 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001692
Christian Costa47b6b942002-12-16 23:07:41 +00001693 return DD_OK;
1694}
1695
1696HRESULT WINAPI
1697GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1698 D3DPRIMITIVETYPE d3dptPrimitiveType,
1699 DWORD dwVertexType,
1700 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1701 DWORD dwVertexCount,
1702 LPWORD lpIndex,
1703 DWORD dwIndexCount,
1704 DWORD dwFlags)
1705{
1706 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001707
Christian Costa47b6b942002-12-16 23:07:41 +00001708 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001709 if (TRACE_ON(ddraw)) {
1710 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1711 }
1712
Lionel Ulmer19e6bf92003-02-12 21:40:25 +00001713 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001714
Lionel Ulmerce3d9682003-01-02 19:46:46 +00001715 return DD_OK;
1716}
1717
1718HRESULT WINAPI
1719GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1720 D3DPRIMITIVETYPE d3dptPrimitiveType,
1721 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1722 DWORD dwStartVertex,
1723 DWORD dwNumVertices,
1724 DWORD dwFlags)
1725{
1726 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1727 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001728 D3DDRAWPRIMITIVESTRIDEDDATA strided;
Lionel Ulmerce3d9682003-01-02 19:46:46 +00001729
1730 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001731 if (TRACE_ON(ddraw)) {
1732 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1733 }
Lionel Ulmerce3d9682003-01-02 19:46:46 +00001734
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001735 if (vb_impl->processed) {
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001736 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1737 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1738
1739 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1740 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1741 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1742
Lionel Ulmer19e6bf92003-02-12 21:40:25 +00001743 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1744 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001745
1746 } else {
Lionel Ulmer19e6bf92003-02-12 21:40:25 +00001747 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1748 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001749 }
Lionel Ulmerce3d9682003-01-02 19:46:46 +00001750
1751 return DD_OK;
1752}
1753
1754HRESULT WINAPI
1755GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1756 D3DPRIMITIVETYPE d3dptPrimitiveType,
1757 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1758 DWORD dwStartVertex,
1759 DWORD dwNumVertices,
1760 LPWORD lpwIndices,
1761 DWORD dwIndexCount,
1762 DWORD dwFlags)
1763{
1764 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1765 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001766 D3DDRAWPRIMITIVESTRIDEDDATA strided;
Lionel Ulmerce3d9682003-01-02 19:46:46 +00001767
1768 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
Lionel Ulmer5f87d772003-01-03 19:10:48 +00001769 if (TRACE_ON(ddraw)) {
1770 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1771 }
Lionel Ulmerce3d9682003-01-02 19:46:46 +00001772
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001773 if (vb_impl->processed) {
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001774 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1775 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1776
1777 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1778 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1779 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1780
Lionel Ulmer19e6bf92003-02-12 21:40:25 +00001781 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1782 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001783
1784 } else {
Lionel Ulmer19e6bf92003-02-12 21:40:25 +00001785 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1786 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
Lionel Ulmerc064dcf2003-01-03 21:07:22 +00001787 }
Lionel Ulmerce3d9682003-01-02 19:46:46 +00001788
Christian Costa47b6b942002-12-16 23:07:41 +00001789 return DD_OK;
1790}
1791
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001792/* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1793static BOOLEAN
Lionel Ulmer11b1b942003-05-20 02:15:24 +00001794handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001795{
1796 BOOLEAN is_complement = FALSE;
1797 BOOLEAN is_alpha_replicate = FALSE;
1798 BOOLEAN handled = TRUE;
1799 GLenum src;
1800 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1801 int num;
1802
1803 if (is_color) {
1804 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1805 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1806 else {
1807 handled = FALSE;
1808 num = 0;
1809 }
1810 if (tex_op == D3DTOP_SELECTARG2) {
1811 num = 1 - num;
1812 }
1813 } else {
1814 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1815 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1816 else {
1817 handled = FALSE;
1818 num = 0;
1819 }
1820 if (tex_op == D3DTOP_SELECTARG2) {
1821 num = 1 - num;
1822 }
1823 }
1824
1825 if (dwState & D3DTA_COMPLEMENT) {
1826 is_complement = TRUE;
1827 }
1828 if (dwState & D3DTA_ALPHAREPLICATE) {
1829 is_alpha_replicate = TRUE;
1830 }
1831 dwState &= D3DTA_SELECTMASK;
1832 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1833 dwState = D3DTA_DIFFUSE;
1834 }
1835
1836 switch (dwState) {
1837 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
Lionel Ulmera872c782003-05-12 03:09:17 +00001838 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001839 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
Lionel Ulmer11b1b942003-05-20 02:15:24 +00001840 case D3DTA_TFACTOR: {
1841 /* Get the constant value from the current rendering state */
1842 GLfloat color[4];
1843 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1844
1845 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1846 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1847 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1848 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1849 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1850
1851 src = GL_CONSTANT_EXT;
1852 } break;
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001853 default: src = GL_TEXTURE; handled = FALSE; break;
1854 }
1855
1856 if (is_color) {
Lionel Ulmera872c782003-05-12 03:09:17 +00001857 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001858 if (is_alpha_replicate) {
Lionel Ulmera872c782003-05-12 03:09:17 +00001859 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001860 } else {
Lionel Ulmera872c782003-05-12 03:09:17 +00001861 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001862 }
1863 } else {
Lionel Ulmera872c782003-05-12 03:09:17 +00001864 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1865 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001866 }
1867
1868 return handled;
1869}
1870
Christian Costa47b6b942002-12-16 23:07:41 +00001871HRESULT WINAPI
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001872GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1873 DWORD dwStage,
1874 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1875 DWORD dwState)
1876{
1877 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
Lionel Ulmer815118a2003-06-16 01:23:58 +00001878 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001879 const char *type;
1880 DWORD prev_state;
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00001881 GLenum unit;
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001882
1883 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1884
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00001885 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1886 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1887 return DD_OK;
1888 }
Lionel Ulmer1213c172003-01-07 23:08:31 +00001889
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00001890 unit = GL_TEXTURE0_WINE + dwStage;
1891 if (unit != glThis->current_active_tex_unit) {
1892 GL_extensions.glActiveTexture(unit);
1893 glThis->current_active_tex_unit = unit;
1894 }
1895
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001896 switch (d3dTexStageStateType) {
1897#define GEN_CASE(a) case a: type = #a; break
1898 GEN_CASE(D3DTSS_COLOROP);
1899 GEN_CASE(D3DTSS_COLORARG1);
1900 GEN_CASE(D3DTSS_COLORARG2);
1901 GEN_CASE(D3DTSS_ALPHAOP);
1902 GEN_CASE(D3DTSS_ALPHAARG1);
1903 GEN_CASE(D3DTSS_ALPHAARG2);
1904 GEN_CASE(D3DTSS_BUMPENVMAT00);
1905 GEN_CASE(D3DTSS_BUMPENVMAT01);
1906 GEN_CASE(D3DTSS_BUMPENVMAT10);
1907 GEN_CASE(D3DTSS_BUMPENVMAT11);
1908 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1909 GEN_CASE(D3DTSS_ADDRESS);
1910 GEN_CASE(D3DTSS_ADDRESSU);
1911 GEN_CASE(D3DTSS_ADDRESSV);
1912 GEN_CASE(D3DTSS_BORDERCOLOR);
1913 GEN_CASE(D3DTSS_MAGFILTER);
1914 GEN_CASE(D3DTSS_MINFILTER);
1915 GEN_CASE(D3DTSS_MIPFILTER);
1916 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1917 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1918 GEN_CASE(D3DTSS_MAXANISOTROPY);
1919 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1920 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1921 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001922#undef GEN_CASE
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001923 default: type = "UNKNOWN";
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001924 }
1925
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001926 /* Store the values in the state array */
1927 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1928 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1929 /* Some special cases when one state modifies more than one... */
1930 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1931 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1932 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1933 }
Lionel Ulmerf87c54f2003-06-04 23:16:28 +00001934
1935 ENTER_GL();
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001936
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001937 switch (d3dTexStageStateType) {
1938 case D3DTSS_MINFILTER:
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001939 case D3DTSS_MIPFILTER:
Lionel Ulmer1213c172003-01-07 23:08:31 +00001940 if (TRACE_ON(ddraw)) {
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001941 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1942 switch ((D3DTEXTUREMINFILTER) dwState) {
1943 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1944 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1945 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1946 }
1947 } else {
1948 switch ((D3DTEXTUREMIPFILTER) dwState) {
1949 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1950 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1951 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1952 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1953 }
Lionel Ulmer1213c172003-01-07 23:08:31 +00001954 }
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001955 }
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001956 break;
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001957
1958 case D3DTSS_MAGFILTER:
Lionel Ulmer1213c172003-01-07 23:08:31 +00001959 if (TRACE_ON(ddraw)) {
1960 switch ((D3DTEXTUREMAGFILTER) dwState) {
Lionel Ulmer4bc97ce2003-08-02 00:41:03 +00001961 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1962 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001963 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
Lionel Ulmer1213c172003-01-07 23:08:31 +00001964 }
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001965 }
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00001966 break;
Lionel Ulmerda66dad2003-01-02 19:43:08 +00001967
1968 case D3DTSS_ADDRESS:
1969 case D3DTSS_ADDRESSU:
1970 case D3DTSS_ADDRESSV: {
Lionel Ulmerda66dad2003-01-02 19:43:08 +00001971 switch ((D3DTEXTUREADDRESS) dwState) {
Lionel Ulmer934d97b2003-06-04 23:19:14 +00001972 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1973 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1974 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
Lionel Ulmer1d45ab42003-08-05 18:28:07 +00001975 case D3DTADDRESS_MIRROR:
Alexandre Julliardebe3c522004-12-09 14:07:59 +00001976 if (GL_extensions.mirrored_repeat) {
Lionel Ulmer1d45ab42003-08-05 18:28:07 +00001977 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1978 } else {
1979 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1980 }
1981 break;
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001982 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
Lionel Ulmerda66dad2003-01-02 19:43:08 +00001983 }
Lionel Ulmerda66dad2003-01-02 19:43:08 +00001984 } break;
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001985
1986 case D3DTSS_ALPHAOP:
1987 case D3DTSS_COLOROP: {
1988 int scale = 1;
Lionel Ulmera872c782003-05-12 03:09:17 +00001989 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
Lionel Ulmer449f6b22003-05-11 03:44:53 +00001990 const char *value;
1991 int handled = 1;
1992
1993 switch (dwState) {
1994#define GEN_CASE(a) case a: value = #a; break
1995 GEN_CASE(D3DTOP_DISABLE);
1996 GEN_CASE(D3DTOP_SELECTARG1);
1997 GEN_CASE(D3DTOP_SELECTARG2);
1998 GEN_CASE(D3DTOP_MODULATE);
1999 GEN_CASE(D3DTOP_MODULATE2X);
2000 GEN_CASE(D3DTOP_MODULATE4X);
2001 GEN_CASE(D3DTOP_ADD);
2002 GEN_CASE(D3DTOP_ADDSIGNED);
2003 GEN_CASE(D3DTOP_ADDSIGNED2X);
2004 GEN_CASE(D3DTOP_SUBTRACT);
2005 GEN_CASE(D3DTOP_ADDSMOOTH);
2006 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
2007 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
2008 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
2009 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
2010 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
2011 GEN_CASE(D3DTOP_PREMODULATE);
2012 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
2013 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
2014 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
2015 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
2016 GEN_CASE(D3DTOP_BUMPENVMAP);
2017 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
2018 GEN_CASE(D3DTOP_DOTPRODUCT3);
2019 GEN_CASE(D3DTOP_FORCE_DWORD);
2020#undef GEN_CASE
2021 default: value = "UNKNOWN";
2022 }
2023
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00002024 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002025 glDisable(GL_TEXTURE_2D);
2026 TRACE(" disabling 2D texturing.\n");
2027 } else {
Lionel Ulmer63d9cfc2003-11-18 23:20:25 +00002028 /* Re-enable texturing only if COLOROP was not already disabled... */
2029 if ((glThis->current_bound_texture[dwStage] != NULL) &&
2030 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002031 glEnable(GL_TEXTURE_2D);
2032 TRACE(" enabling 2D texturing.\n");
2033 }
2034
Lionel Ulmera872c782003-05-12 03:09:17 +00002035 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
Lionel Ulmer63d9cfc2003-11-18 23:20:25 +00002036 if ((dwState != D3DTOP_DISABLE) &&
2037 (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE)) {
Lionel Ulmer815118a2003-06-16 01:23:58 +00002038 if (glThis->current_tex_env != GL_COMBINE_EXT) {
2039 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
2040 glThis->current_tex_env = GL_COMBINE_EXT;
2041 }
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002042 }
2043
2044 /* Now set up the operand correctly */
2045 switch (dwState) {
2046 case D3DTOP_DISABLE:
2047 /* Contrary to the docs, alpha can be disabled when colorop is enabled
2048 and it works, so ignore this op */
2049 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
2050 break;
2051
2052 case D3DTOP_SELECTARG1:
2053 case D3DTOP_SELECTARG2:
2054 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
2055 break;
2056
2057 case D3DTOP_MODULATE4X:
2058 scale = scale * 2; /* Drop through */
2059 case D3DTOP_MODULATE2X:
2060 scale = scale * 2; /* Drop through */
2061 case D3DTOP_MODULATE:
2062 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
2063 break;
2064
2065 case D3DTOP_ADD:
2066 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
2067 break;
2068
2069 case D3DTOP_ADDSIGNED2X:
2070 scale = scale * 2; /* Drop through */
2071 case D3DTOP_ADDSIGNED:
Lionel Ulmera872c782003-05-12 03:09:17 +00002072 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002073 break;
2074
Lionel Ulmerc312ff92003-06-04 21:53:43 +00002075 /* For the four blending modes, use the Arg2 parameter */
2076 case D3DTOP_BLENDDIFFUSEALPHA:
2077 case D3DTOP_BLENDTEXTUREALPHA:
2078 case D3DTOP_BLENDFACTORALPHA:
2079 case D3DTOP_BLENDCURRENTALPHA: {
2080 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
2081
2082 switch (dwState) {
2083 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
2084 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
2085 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
2086 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
2087 }
2088
Lionel Ulmer21856fb2003-06-04 23:10:38 +00002089 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
Lionel Ulmerc312ff92003-06-04 21:53:43 +00002090 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
2091 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
2092 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
2093 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
2094 } break;
2095
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002096 default:
2097 handled = FALSE;
2098 break;
2099 }
2100 }
2101
2102 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
2103 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
2104 /* Switch the arguments if needed... */
2105 if (d3dTexStageStateType == D3DTSS_COLOROP) {
Lionel Ulmer11b1b942003-05-20 02:15:24 +00002106 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002107 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
2108 dwState);
Lionel Ulmer11b1b942003-05-20 02:15:24 +00002109 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002110 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
2111 dwState);
2112 } else {
Lionel Ulmer11b1b942003-05-20 02:15:24 +00002113 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002114 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
2115 dwState);
Lionel Ulmer11b1b942003-05-20 02:15:24 +00002116 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002117 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2118 dwState);
2119 }
2120 }
2121
2122 if (handled) {
2123 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2124 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2125 } else {
Lionel Ulmera872c782003-05-12 03:09:17 +00002126 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002127 }
2128 TRACE(" Stage type is : %s => %s\n", type, value);
2129 } else {
2130 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2131 }
2132 } break;
2133
2134 case D3DTSS_COLORARG1:
2135 case D3DTSS_COLORARG2:
2136 case D3DTSS_ALPHAARG1:
2137 case D3DTSS_ALPHAARG2: {
2138 const char *value, *value_comp = "", *value_alpha = "";
2139 BOOLEAN handled;
2140 D3DTEXTUREOP tex_op;
2141
2142 switch (dwState & D3DTA_SELECTMASK) {
2143#define GEN_CASE(a) case a: value = #a; break
2144 GEN_CASE(D3DTA_DIFFUSE);
2145 GEN_CASE(D3DTA_CURRENT);
2146 GEN_CASE(D3DTA_TEXTURE);
2147 GEN_CASE(D3DTA_TFACTOR);
2148 GEN_CASE(D3DTA_SPECULAR);
2149#undef GEN_CASE
2150 default: value = "UNKNOWN";
2151 }
2152 if (dwState & D3DTA_COMPLEMENT) {
2153 value_comp = " | D3DTA_COMPLEMENT";
2154 }
2155 if (dwState & D3DTA_ALPHAREPLICATE) {
2156 value_alpha = " | D3DTA_ALPHAREPLICATE";
2157 }
2158
2159 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2160 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2161 } else {
2162 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2163 }
2164
Lionel Ulmer11b1b942003-05-20 02:15:24 +00002165 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002166
2167 if (handled) {
2168 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2169 } else {
2170 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2171 }
2172 } break;
Lionel Ulmera872c782003-05-12 03:09:17 +00002173
2174 case D3DTSS_MIPMAPLODBIAS: {
2175 D3DVALUE value = *((D3DVALUE *) &dwState);
2176 BOOLEAN handled = TRUE;
2177
Lionel Ulmer50fbe732003-08-05 19:18:19 +00002178 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
Lionel Ulmera872c782003-05-12 03:09:17 +00002179 handled = FALSE;
2180
2181 if (handled) {
2182 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
Lionel Ulmer50fbe732003-08-05 19:18:19 +00002183 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
Lionel Ulmera872c782003-05-12 03:09:17 +00002184 } else {
2185 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2186 }
2187 } break;
2188
2189 case D3DTSS_MAXMIPLEVEL:
Lionel Ulmer3f61d282003-06-04 23:38:22 +00002190 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
Lionel Ulmera872c782003-05-12 03:09:17 +00002191 break;
2192
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002193 case D3DTSS_BORDERCOLOR:
Lionel Ulmer16675022003-05-17 18:30:27 +00002194 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2195 ((dwState >> 16) & 0xFF),
2196 ((dwState >> 8) & 0xFF),
2197 ((dwState >> 0) & 0xFF),
2198 ((dwState >> 24) & 0xFF));
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002199 break;
Lionel Ulmera872c782003-05-12 03:09:17 +00002200
2201 case D3DTSS_TEXCOORDINDEX: {
2202 BOOLEAN handled = TRUE;
2203 const char *value;
2204
2205 switch (dwState & 0xFFFF0000) {
2206#define GEN_CASE(a) case a: value = #a; break
2207 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2208 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2209 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2210 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2211#undef GEN_CASE
2212 default: value = "UNKNOWN";
2213 }
2214 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2215 handled = FALSE;
2216
2217 if (handled) {
2218 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2219 } else {
2220 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2221 }
2222 } break;
2223
2224 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2225 const char *projected = "", *value;
2226 BOOLEAN handled = TRUE;
2227 switch (dwState & 0xFF) {
2228#define GEN_CASE(a) case a: value = #a; break
2229 GEN_CASE(D3DTTFF_DISABLE);
2230 GEN_CASE(D3DTTFF_COUNT1);
2231 GEN_CASE(D3DTTFF_COUNT2);
2232 GEN_CASE(D3DTTFF_COUNT3);
2233 GEN_CASE(D3DTTFF_COUNT4);
2234#undef GEN_CASE
2235 default: value = "UNKNOWN";
2236 }
Lionel Ulmer11b1b942003-05-20 02:15:24 +00002237 if (dwState & D3DTTFF_PROJECTED) {
Lionel Ulmera872c782003-05-12 03:09:17 +00002238 projected = " | D3DTTFF_PROJECTED";
Lionel Ulmer11b1b942003-05-20 02:15:24 +00002239 handled = FALSE;
2240 }
Lionel Ulmera872c782003-05-12 03:09:17 +00002241
Lionel Ulmer11b1b942003-05-20 02:15:24 +00002242 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2243 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2244 }
Lionel Ulmera872c782003-05-12 03:09:17 +00002245
Alexandre Julliardebe3c522004-12-09 14:07:59 +00002246 if (handled) {
Lionel Ulmera872c782003-05-12 03:09:17 +00002247 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2248 } else {
2249 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2250 }
2251 } break;
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002252
2253 default:
Lionel Ulmer449f6b22003-05-11 03:44:53 +00002254 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2255 break;
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002256 }
Lionel Ulmerf87c54f2003-06-04 23:16:28 +00002257
2258 LEAVE_GL();
2259
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002260 return DD_OK;
2261}
2262
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002263static DWORD
2264draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2265{
2266 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2267 DWORD stage;
Lionel Ulmerb6ddd8c2003-11-11 00:31:16 +00002268 BOOLEAN enable_colorkey = FALSE;
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002269
2270 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2271 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00002272 GLenum unit;
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002273
Lionel Ulmer63d9cfc2003-11-18 23:20:25 +00002274 /* If this stage is disabled, no need to go further... */
2275 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE)
2276 break;
2277
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002278 /* First check if we need to bind any other texture for this stage */
2279 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2280 if (This->current_texture[stage] == NULL) {
2281 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00002282
2283 unit = GL_TEXTURE0_WINE + stage;
2284 if (unit != glThis->current_active_tex_unit) {
2285 GL_extensions.glActiveTexture(unit);
2286 glThis->current_active_tex_unit = unit;
2287 }
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002288 glBindTexture(GL_TEXTURE_2D, 0);
Lionel Ulmer63d9cfc2003-11-18 23:20:25 +00002289 glDisable(GL_TEXTURE_2D);
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002290 } else {
Lionel Ulmeracdc84e2005-04-11 12:51:22 +00002291 GLenum tex_name = gltex_get_tex_name(surf_ptr);
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002292
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00002293 unit = GL_TEXTURE0_WINE + stage;
2294 if (unit != glThis->current_active_tex_unit) {
2295 GL_extensions.glActiveTexture(unit);
2296 glThis->current_active_tex_unit = unit;
2297 }
2298
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002299 if (glThis->current_bound_texture[stage] == NULL) {
2300 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
Lionel Ulmered883042003-06-04 23:36:48 +00002301 TRACE(" enabling 2D texturing and");
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002302 glEnable(GL_TEXTURE_2D);
2303 }
2304 }
2305 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2306 glBindTexture(GL_TEXTURE_2D, tex_name);
2307 }
2308
2309 glThis->current_bound_texture[stage] = This->current_texture[stage];
Lionel Ulmered883042003-06-04 23:36:48 +00002310 } else {
2311 if (glThis->current_bound_texture[stage] == NULL) {
2312 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2313 } else {
2314 TRACE(" using already bound texture id %d for stage %ld.\n",
2315 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2316 }
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002317 }
2318
2319 /* If no texure valid for this stage, go out of the loop */
2320 if (This->current_texture[stage] == NULL) break;
2321
2322 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2323 This will also update the various texture parameters if needed.
2324 */
2325 gltex_upload_texture(surf_ptr, This, stage);
Lionel Ulmerb6ddd8c2003-11-11 00:31:16 +00002326
2327 /* And finally check for color-keying (only on first stage) */
2328 if (This->current_texture[stage]->surface_desc.dwFlags & DDSD_CKSRCBLT) {
2329 if (stage == 0) {
2330 enable_colorkey = TRUE;
2331 } else {
2332 static BOOL warn = FALSE;
2333 if (warn == FALSE) {
2334 warn = TRUE;
2335 WARN(" Surface has color keying on stage different from 0 (%ld) !", stage);
2336 }
2337 }
2338 } else {
2339 if (stage == 0) {
2340 enable_colorkey = FALSE;
2341 }
2342 }
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002343 }
2344
Lionel Ulmerb6ddd8c2003-11-11 00:31:16 +00002345 /* Apparently, whatever the state of BLEND, color keying is always activated for 'old' D3D versions */
2346 if (((This->state_block.render_state[D3DRENDERSTATE_COLORKEYENABLE - 1]) ||
Christian Costae64aae02005-02-14 11:09:46 +00002347 (glThis->parent.version == 1)) &&
Lionel Ulmerb6ddd8c2003-11-11 00:31:16 +00002348 (enable_colorkey)) {
2349 TRACE(" colorkey activated.\n");
2350
2351 if (glThis->alpha_test == FALSE) {
2352 glEnable(GL_ALPHA_TEST);
2353 glThis->alpha_test = TRUE;
2354 }
2355 if ((glThis->current_alpha_test_func != GL_NOTEQUAL) || (glThis->current_alpha_test_ref != 0.0)) {
Alexandre Julliardebe3c522004-12-09 14:07:59 +00002356 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1]) {
Lionel Ulmerb6ddd8c2003-11-11 00:31:16 +00002357 static BOOL warn = FALSE;
2358 if (warn == FALSE) {
2359 warn = TRUE;
2360 WARN(" Overriding application-given alpha test values - some graphical glitches may appear !\n");
2361 }
2362 }
2363 glThis->current_alpha_test_func = GL_NOTEQUAL;
2364 glThis->current_alpha_test_ref = 0.0;
2365 glAlphaFunc(GL_NOTEQUAL, 0.0);
2366 }
2367 /* Some sanity checks should be added here if a game mixes alphatest + color keying...
2368 Only one has been found for now, and the ALPHAFUNC is 'Always' so it works :-) */
2369 } else {
2370 if (This->state_block.render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == FALSE) {
2371 glDisable(GL_ALPHA_TEST);
2372 glThis->alpha_test = FALSE;
2373 }
2374 /* Maybe we should restore here the application-given alpha test states ? */
2375 }
2376
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002377 return stage;
2378}
2379
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002380HRESULT WINAPI
Lionel Ulmer90bf1f22002-12-24 00:53:50 +00002381GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2382 DWORD dwStage,
2383 LPDIRECTDRAWSURFACE7 lpTexture2)
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002384{
Lionel Ulmer90bf1f22002-12-24 00:53:50 +00002385 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002386
2387 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00002388
2389 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2390 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2391 if (lpTexture2 != NULL) {
2392 WARN(" setting a texture to a non-supported texture stage !\n");
2393 }
2394 return DD_OK;
2395 }
Lionel Ulmer1213c172003-01-07 23:08:31 +00002396
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002397 if (This->current_texture[dwStage] != NULL) {
Lionel Ulmer07f12692003-01-05 01:04:55 +00002398 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002399 }
2400
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002401 if (lpTexture2 == NULL) {
Lionel Ulmer07f12692003-01-05 01:04:55 +00002402 This->current_texture[dwStage] = NULL;
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002403 } else {
Lionel Ulmer90bf1f22002-12-24 00:53:50 +00002404 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002405 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
Lionel Ulmer934d97b2003-06-04 23:19:14 +00002406 This->current_texture[dwStage] = tex_impl;
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002407 }
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002408
2409 return DD_OK;
2410}
2411
Mike McCormack82f9c972005-08-01 09:22:26 +00002412static HRESULT WINAPI
Lionel Ulmer5261f032002-12-02 21:39:34 +00002413GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2414 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2415{
2416 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2417 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2418
2419 fill_opengl_caps_7(lpD3DHELDevDesc);
2420
2421 TRACE(" returning caps : no dump function yet.\n");
2422
2423 return DD_OK;
2424}
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002425
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002426HRESULT WINAPI
2427GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2428 LPD3DMATERIAL7 lpMat)
2429{
2430 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2431 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2432
2433 if (TRACE_ON(ddraw)) {
Francois Gouget0edbaf72005-11-10 12:14:56 +00002434 TRACE(" material is :\n");
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002435 dump_D3DMATERIAL7(lpMat);
2436 }
2437
2438 This->current_material = *lpMat;
2439
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002440 ENTER_GL();
Lionel Ulmerae10e9c2003-01-02 20:05:48 +00002441 glMaterialfv(GL_FRONT_AND_BACK,
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002442 GL_DIFFUSE,
2443 (float *) &(This->current_material.u.diffuse));
Lionel Ulmerae10e9c2003-01-02 20:05:48 +00002444 glMaterialfv(GL_FRONT_AND_BACK,
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002445 GL_AMBIENT,
2446 (float *) &(This->current_material.u1.ambient));
Lionel Ulmerae10e9c2003-01-02 20:05:48 +00002447 glMaterialfv(GL_FRONT_AND_BACK,
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002448 GL_SPECULAR,
2449 (float *) &(This->current_material.u2.specular));
Lionel Ulmerae10e9c2003-01-02 20:05:48 +00002450 glMaterialfv(GL_FRONT_AND_BACK,
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002451 GL_EMISSION,
2452 (float *) &(This->current_material.u3.emissive));
Lionel Ulmerae10e9c2003-01-02 20:05:48 +00002453 glMaterialf(GL_FRONT_AND_BACK,
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002454 GL_SHININESS,
2455 This->current_material.u4.power); /* Not sure about this... */
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002456 LEAVE_GL();
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002457
2458 return DD_OK;
2459}
2460
Antoine Chavasseb65e7902005-06-07 21:34:40 +00002461static LPD3DLIGHT7 get_light(IDirect3DDeviceImpl *This, DWORD dwLightIndex)
2462{
2463 if (dwLightIndex >= This->num_set_lights)
2464 {
2465 /* Extend, or allocate the light parameters array. */
2466 DWORD newlightnum = dwLightIndex + 1;
2467 LPD3DLIGHT7 newarrayptr = NULL;
2468
2469 if (This->light_parameters)
2470 newarrayptr = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2471 This->light_parameters, newlightnum * sizeof(D3DLIGHT7));
2472 else
2473 newarrayptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2474 newlightnum * sizeof(D3DLIGHT7));
2475
2476 if (!newarrayptr)
2477 return NULL;
2478
2479 This->light_parameters = newarrayptr;
2480 This->num_set_lights = newlightnum;
2481 }
2482
2483 return &This->light_parameters[dwLightIndex];
2484}
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002485
2486HRESULT WINAPI
2487GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2488 DWORD dwLightIndex,
2489 LPD3DLIGHT7 lpLight)
2490{
2491 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00002492 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
Antoine Chavasseb65e7902005-06-07 21:34:40 +00002493 LPD3DLIGHT7 lpdestlight = get_light( This, dwLightIndex );
2494
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002495 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2496
2497 if (TRACE_ON(ddraw)) {
Francois Gouget0edbaf72005-11-10 12:14:56 +00002498 TRACE(" setting light :\n");
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002499 dump_D3DLIGHT7(lpLight);
2500 }
2501
Antoine Chavasseb65e7902005-06-07 21:34:40 +00002502 /* DirectX7 documentation states that this function can return
2503 DDERR_OUTOFMEMORY, so we do just that in case of an allocation
2504 error (which is the only reason why get_light() can fail). */
2505 if( !lpdestlight )
2506 return DDERR_OUTOFMEMORY;
2507
2508 *lpdestlight = *lpLight;
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002509
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00002510 /* Some checks to print out nice warnings :-) */
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002511 switch (lpLight->dltType) {
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00002512 case D3DLIGHT_DIRECTIONAL:
2513 case D3DLIGHT_POINT:
2514 /* These are handled properly... */
2515 break;
Lionel Ulmerd0f15692003-01-03 21:03:15 +00002516
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00002517 case D3DLIGHT_SPOT:
2518 if ((lpLight->dvTheta != 0.0) ||
2519 (lpLight->dvTheta != lpLight->dvPhi)) {
2520 ERR("dvTheta not fully supported yet !\n");
Lionel Ulmerd0f15692003-01-03 21:03:15 +00002521 }
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00002522 break;
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002523
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00002524 default:
2525 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002526 }
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00002527
2528 /* This will force the Light setting on next drawing of primitives */
2529 glThis->transform_state = GL_TRANSFORM_NONE;
2530
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002531 return DD_OK;
2532}
2533
2534HRESULT WINAPI
2535GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2536 DWORD dwLightIndex,
2537 BOOL bEnable)
2538{
Antoine Chavasseb65e7902005-06-07 21:34:40 +00002539 int lightslot = -1, i;
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002540 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
Antoine Chavasseb65e7902005-06-07 21:34:40 +00002541 LPD3DLIGHT7 lpdestlight = get_light(This, dwLightIndex);
2542
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002543 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
Antoine Chavasseb65e7902005-06-07 21:34:40 +00002544
2545 /* The DirectX doc isn't as explicit as for SetLight as whether we can
2546 return this from this function, but it doesn't state otherwise. */
2547 if (!lpdestlight)
2548 return DDERR_OUTOFMEMORY;
2549
2550 /* If this light hasn't been set, initialise it with default values. */
2551 if (lpdestlight->dltType == 0)
2552 {
2553 TRACE("setting default light parameters\n");
2554
2555 /* We always use HEAP_ZERO_MEMORY when allocating the light_parameters
2556 array, so we only have to setup anything that shoud not be zero. */
2557 lpdestlight->dltType = D3DLIGHT_DIRECTIONAL;
2558 lpdestlight->dcvDiffuse.u1.r = 1.f;
2559 lpdestlight->dcvDiffuse.u2.g = 1.f;
2560 lpdestlight->dcvDiffuse.u3.b = 1.f;
2561 lpdestlight->dvDirection.u3.z = 1.f;
2562 }
2563
2564 /* Look for this light in the active lights array. */
2565 for (i = 0; i < This->max_active_lights; i++)
2566 if (This->active_lights[i] == dwLightIndex)
2567 {
2568 lightslot = i;
2569 break;
2570 }
2571
2572 /* If we didn't find it, let's find the first available slot, if any. */
2573 if (lightslot == -1)
2574 for (i = 0; i < This->max_active_lights; i++)
2575 if (This->active_lights[i] == ~0)
2576 {
2577 lightslot = i;
2578 break;
2579 }
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002580
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00002581 ENTER_GL();
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002582 if (bEnable) {
Antoine Chavasseb65e7902005-06-07 21:34:40 +00002583 if (lightslot == -1)
2584 {
2585 /* This means that the app is trying to enable more lights than
2586 the maximum possible indicated in the caps.
2587
2588 Windows actually let you do this, and disable one of the
2589 previously enabled lights to let you enable this one.
2590
2591 It's not documented and I'm not sure how windows pick which light
2592 to disable to make room for this one. */
2593 FIXME("Enabling more light than the maximum is not supported yet.");
2594 return D3D_OK;
2595 }
2596
2597 glEnable(GL_LIGHT0 + lightslot);
2598
2599
2600 if (This->active_lights[lightslot] == ~0)
2601 {
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00002602 /* This light gets active... Need to update its parameters to GL before the next drawing */
2603 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
Antoine Chavasseb65e7902005-06-07 21:34:40 +00002604
2605 This->active_lights[lightslot] = dwLightIndex;
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00002606 glThis->transform_state = GL_TRANSFORM_NONE;
2607 }
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002608 } else {
Antoine Chavasseb65e7902005-06-07 21:34:40 +00002609 glDisable(GL_LIGHT0 + lightslot);
2610 This->active_lights[lightslot] = ~0;
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002611 }
2612
Antoine Chavasseb65e7902005-06-07 21:34:40 +00002613 LEAVE_GL();
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002614 return DD_OK;
2615}
2616
Christoph Frick7f4cb062003-01-07 19:42:26 +00002617HRESULT WINAPI
Stefan Dösinger6e271522006-02-11 20:30:48 +01002618GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, D3DVALUE* pPlaneEquation)
Christoph Frick7f4cb062003-01-07 19:42:26 +00002619{
Alexandre Julliardf5f7a182004-09-08 01:50:37 +00002620 IDirect3DDeviceImpl *This = (IDirect3DDeviceImpl *)iface;
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00002621 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
Christoph Frick7f4cb062003-01-07 19:42:26 +00002622
2623 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2624
Lionel Ulmer86f69132003-05-19 23:03:38 +00002625 if (dwIndex >= This->max_clipping_planes) {
Christoph Frick7f4cb062003-01-07 19:42:26 +00002626 return DDERR_INVALIDPARAMS;
2627 }
2628
2629 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2630
Lionel Ulmer86f69132003-05-19 23:03:38 +00002631 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00002632
2633 /* This is to force the reset of the transformation matrices on the next drawing.
2634 * This is needed to use the correct matrices for the various clipping planes.
2635 */
2636 glThis->transform_state = GL_TRANSFORM_NONE;
2637
Christoph Frick7f4cb062003-01-07 19:42:26 +00002638 return D3D_OK;
2639}
2640
Mike McCormack82f9c972005-08-01 09:22:26 +00002641static HRESULT WINAPI
Lionel Ulmer86f69132003-05-19 23:03:38 +00002642GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2643 LPD3DVIEWPORT7 lpData)
2644{
2645 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2646 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2647
2648 if (TRACE_ON(ddraw)) {
Francois Gouget0edbaf72005-11-10 12:14:56 +00002649 TRACE(" viewport is :\n");
Lionel Ulmer86f69132003-05-19 23:03:38 +00002650 TRACE(" - dwX = %ld dwY = %ld\n",
2651 lpData->dwX, lpData->dwY);
2652 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2653 lpData->dwWidth, lpData->dwHeight);
2654 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2655 lpData->dvMinZ, lpData->dvMaxZ);
2656 }
Lionel Ulmer241d3062003-06-04 23:17:23 +00002657 ENTER_GL();
2658
Lionel Ulmer86f69132003-05-19 23:03:38 +00002659 /* Set the viewport */
Lionel Ulmer815118a2003-06-16 01:23:58 +00002660 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2661 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2662 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2663 }
2664 if ((lpData->dwX != This->active_viewport.dwX) ||
2665 (lpData->dwY != This->active_viewport.dwY) ||
2666 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2667 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2668 glViewport(lpData->dwX,
2669 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2670 lpData->dwWidth, lpData->dwHeight);
2671 }
Lionel Ulmer241d3062003-06-04 23:17:23 +00002672
2673 LEAVE_GL();
Lionel Ulmer815118a2003-06-16 01:23:58 +00002674
2675 This->active_viewport = *lpData;
Lionel Ulmer86f69132003-05-19 23:03:38 +00002676
2677 return DD_OK;
2678}
2679
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002680#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2681# define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2682#else
2683# define XCAST(fun) (void*)
2684#endif
2685
Dmitry Timoshkov46256282005-05-27 20:17:35 +00002686static const IDirect3DDevice7Vtbl VTABLE_IDirect3DDevice7 =
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002687{
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002688 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2689 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2690 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
Lionel Ulmer5261f032002-12-02 21:39:34 +00002691 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002692 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2693 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2694 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2695 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2696 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2697 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2698 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
Lionel Ulmer01149452003-01-03 21:05:38 +00002699 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002700 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
Lionel Ulmer86f69132003-05-19 23:03:38 +00002701 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002702 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2703 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002704 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002705 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002706 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002707 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2708 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
Christian Costa4fc7a842003-01-03 21:08:50 +00002709 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002710 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2711 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2712 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
Lionel Ulmer5f49e782002-11-30 19:06:52 +00002713 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2714 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002715 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2716 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
Christian Costa47b6b942002-12-16 23:07:41 +00002717 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2718 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
Lionel Ulmerce3d9682003-01-02 19:46:46 +00002719 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2720 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002721 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
Lionel Ulmer7a025002003-01-02 19:52:22 +00002722 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
Lionel Ulmer90bf1f22002-12-24 00:53:50 +00002723 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002724 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
Lionel Ulmer41fcb0b2002-12-02 18:59:11 +00002725 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002726 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2727 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2728 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2729 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2730 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2731 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00002732 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002733 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
Christoph Frick7f4cb062003-01-07 19:42:26 +00002734 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002735 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2736 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2737};
2738
2739#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2740#undef XCAST
2741#endif
2742
2743
2744#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2745# define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2746#else
2747# define XCAST(fun) (void*)
2748#endif
2749
Dmitry Timoshkov46256282005-05-27 20:17:35 +00002750static const IDirect3DDevice3Vtbl VTABLE_IDirect3DDevice3 =
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002751{
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002752 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2753 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2754 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2755 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2756 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2757 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2758 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2759 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2760 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2761 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2762 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2763 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2764 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2765 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2766 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2767 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2768 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2769 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2770 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2771 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2772 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2773 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2774 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
Christian Costa479c13b2004-08-06 17:30:44 +00002775 XCAST(GetLightState) GL_IDirect3DDeviceImpl_3_2T_GetLightState,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002776 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2777 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2778 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2779 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2780 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2781 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2782 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2783 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2784 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2785 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
Lionel Ulmerce3d9682003-01-02 19:46:46 +00002786 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2787 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002788 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
Lionel Ulmer7a025002003-01-02 19:52:22 +00002789 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
Lionel Ulmer90bf1f22002-12-24 00:53:50 +00002790 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002791 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2792 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2793 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2794};
2795
2796#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2797#undef XCAST
2798#endif
2799
2800
2801#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2802# define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2803#else
2804# define XCAST(fun) (void*)
2805#endif
2806
Dmitry Timoshkov46256282005-05-27 20:17:35 +00002807static const IDirect3DDevice2Vtbl VTABLE_IDirect3DDevice2 =
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002808{
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002809 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2810 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2811 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2812 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
Christian Costabc2cf942003-01-02 20:07:05 +00002813 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002814 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2815 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2816 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2817 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2818 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2819 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2820 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2821 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2822 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2823 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2824 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2825 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2826 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2827 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2828 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2829 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2830 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2831 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2832 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2833 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2834 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2835 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2836 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2837 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2838 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2839 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2840 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2841 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2842};
2843
2844#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2845#undef XCAST
2846#endif
2847
2848
2849#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2850# define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2851#else
2852# define XCAST(fun) (void*)
2853#endif
2854
Dmitry Timoshkov46256282005-05-27 20:17:35 +00002855static const IDirect3DDeviceVtbl VTABLE_IDirect3DDevice =
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002856{
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002857 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2858 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2859 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2860 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2861 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
Christian Costabc2cf942003-01-02 20:07:05 +00002862 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00002863 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2864 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2865 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2866 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2867 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2868 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2869 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2870 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2871 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2872 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2873 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2874 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2875 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2876 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2877 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2878 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2879};
2880
2881#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2882#undef XCAST
2883#endif
2884
Lionel Ulmer608da062002-12-24 01:03:04 +00002885static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
Lionel Ulmer26f51af2003-06-13 23:17:59 +00002886 WINE_GL_BUFFER_TYPE buffer_type,
Lionel Ulmer608da062002-12-24 01:03:04 +00002887 DWORD dwCount,
2888 LPD3DRECT lpRects,
2889 DWORD dwFlags,
2890 DWORD dwColor,
2891 D3DVALUE dvZ,
2892 DWORD dwStencil)
2893{
Lionel Ulmerc577c272003-05-20 04:21:46 +00002894 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
Lionel Ulmer608da062002-12-24 01:03:04 +00002895 GLbitfield bitfield = 0;
Lionel Ulmer86f69132003-05-19 23:03:38 +00002896 D3DRECT rect;
Hans Leidekkerfe442b22004-09-08 01:23:57 +00002897 unsigned int i;
Lionel Ulmer608da062002-12-24 01:03:04 +00002898
2899 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2900 if (TRACE_ON(ddraw)) {
Lionel Ulmer6fb7ed82003-01-02 19:51:25 +00002901 if (dwCount > 0) {
Hans Leidekkerfe442b22004-09-08 01:23:57 +00002902 unsigned int i;
Francois Gouget0edbaf72005-11-10 12:14:56 +00002903 TRACE(" rectangles :\n");
Lionel Ulmer6fb7ed82003-01-02 19:51:25 +00002904 for (i = 0; i < dwCount; i++) {
2905 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2906 }
Lionel Ulmer608da062002-12-24 01:03:04 +00002907 }
2908 }
2909
Lionel Ulmer86f69132003-05-19 23:03:38 +00002910 if (dwCount == 0) {
Lionel Ulmer86f69132003-05-19 23:03:38 +00002911 dwCount = 1;
2912 rect.u1.x1 = 0;
2913 rect.u2.y1 = 0;
2914 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2915 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2916 lpRects = &rect;
Lionel Ulmer608da062002-12-24 01:03:04 +00002917 }
Lionel Ulmer86f69132003-05-19 23:03:38 +00002918
Lionel Ulmer608da062002-12-24 01:03:04 +00002919 /* Clears the screen */
2920 ENTER_GL();
Lionel Ulmerc577c272003-05-20 04:21:46 +00002921
Lionel Ulmer26f51af2003-06-13 23:17:59 +00002922 if (dwFlags & D3DCLEAR_TARGET) {
2923 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2924 /* TODO: optimize here the case where Clear changes all the screen... */
2925 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2926 }
2927 glThis->state[buffer_type] = SURFACE_GL;
Lionel Ulmerc577c272003-05-20 04:21:46 +00002928 }
Lionel Ulmerc577c272003-05-20 04:21:46 +00002929
Lionel Ulmer608da062002-12-24 01:03:04 +00002930 if (dwFlags & D3DCLEAR_ZBUFFER) {
2931 bitfield |= GL_DEPTH_BUFFER_BIT;
Lionel Ulmer815118a2003-06-16 01:23:58 +00002932 if (glThis->depth_mask == FALSE) {
2933 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2934 }
2935 if (dvZ != glThis->prev_clear_Z) {
2936 glClearDepth(dvZ);
2937 glThis->prev_clear_Z = dvZ;
2938 }
Lionel Ulmer608da062002-12-24 01:03:04 +00002939 TRACE(" depth value : %f\n", dvZ);
2940 }
2941 if (dwFlags & D3DCLEAR_STENCIL) {
2942 bitfield |= GL_STENCIL_BUFFER_BIT;
Lionel Ulmer815118a2003-06-16 01:23:58 +00002943 if (dwStencil != glThis->prev_clear_stencil) {
2944 glClearStencil(dwStencil);
2945 glThis->prev_clear_stencil = dwStencil;
2946 }
Lionel Ulmer608da062002-12-24 01:03:04 +00002947 TRACE(" stencil value : %ld\n", dwStencil);
2948 }
2949 if (dwFlags & D3DCLEAR_TARGET) {
2950 bitfield |= GL_COLOR_BUFFER_BIT;
Lionel Ulmer815118a2003-06-16 01:23:58 +00002951 if (dwColor != glThis->prev_clear_color) {
2952 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2953 ((dwColor >> 8) & 0xFF) / 255.0,
2954 ((dwColor >> 0) & 0xFF) / 255.0,
2955 ((dwColor >> 24) & 0xFF) / 255.0);
2956 glThis->prev_clear_color = dwColor;
2957 }
Lionel Ulmer608da062002-12-24 01:03:04 +00002958 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2959 }
Lionel Ulmer86f69132003-05-19 23:03:38 +00002960
2961 glEnable(GL_SCISSOR_TEST);
2962 for (i = 0; i < dwCount; i++) {
2963 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2964 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2965 glClear(bitfield);
2966 }
2967 glDisable(GL_SCISSOR_TEST);
Lionel Ulmer608da062002-12-24 01:03:04 +00002968
2969 if (dwFlags & D3DCLEAR_ZBUFFER) {
Lionel Ulmer815118a2003-06-16 01:23:58 +00002970 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
Lionel Ulmer608da062002-12-24 01:03:04 +00002971 }
2972
2973 LEAVE_GL();
2974
2975 return DD_OK;
2976}
2977
Lionel Ulmer26f51af2003-06-13 23:17:59 +00002978static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2979 DWORD dwCount,
2980 LPD3DRECT lpRects,
2981 DWORD dwFlags,
2982 DWORD dwColor,
2983 D3DVALUE dvZ,
2984 DWORD dwStencil)
2985{
2986 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2987}
2988
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00002989static HRESULT
2990setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2991 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
Lionel Ulmer6fb7ed82003-01-02 19:51:25 +00002992{
Lionel Ulmer26f51af2003-06-13 23:17:59 +00002993 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2994 WINE_GL_BUFFER_TYPE buffer_type;
Lionel Ulmer26f51af2003-06-13 23:17:59 +00002995
2996 /* First check if we BLT to the backbuffer... */
2997 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2998 buffer_type = WINE_GL_BUFFER_BACK;
2999 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3000 buffer_type = WINE_GL_BUFFER_FRONT;
3001 } else {
3002 ERR("Only BLT override to front or back-buffer is supported for now !\n");
3003 return DDERR_INVALIDPARAMS;
3004 }
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003005
3006 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
3007 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
3008 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
3009 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
3010 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3011 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
3012 * GL to do it.
3013 */
3014 return DDERR_INVALIDPARAMS;
3015 }
3016 *buffer_type_p = buffer_type;
Lionel Ulmer26f51af2003-06-13 23:17:59 +00003017
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003018 return DD_OK;
3019}
3020
3021HRESULT
3022d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
3023 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
3024 DWORD dwFlags, LPDDBLTFX lpbltfx)
3025{
3026 WINE_GL_BUFFER_TYPE buffer_type;
3027 D3DRECT rect;
3028
Lionel Ulmer26f51af2003-06-13 23:17:59 +00003029 if (rdst) {
3030 rect.u1.x1 = rdst->left;
3031 rect.u2.y1 = rdst->top;
3032 rect.u3.x2 = rdst->right;
3033 rect.u4.y2 = rdst->bottom;
3034 } else {
3035 rect.u1.x1 = 0;
3036 rect.u2.y1 = 0;
3037 rect.u3.x2 = This->surface_desc.dwWidth;
3038 rect.u4.y2 = This->surface_desc.dwHeight;
3039 }
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003040
3041 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
Lionel Ulmer26f51af2003-06-13 23:17:59 +00003042
Lionel Ulmer6fb7ed82003-01-02 19:51:25 +00003043 if (dwFlags & DDBLT_COLORFILL) {
3044 /* This is easy to handle for the D3D Device... */
Lionel Ulmerf0339d22003-06-13 16:29:18 +00003045 DWORD color;
Mike McCormack82f9c972005-08-01 09:22:26 +00003046 GLint prev_draw;
Lionel Ulmerf0339d22003-06-13 16:29:18 +00003047
Lionel Ulmerf0339d22003-06-13 16:29:18 +00003048 /* The color as given in the Blt function is in the format of the frame-buffer...
3049 * 'clear' expect it in ARGB format => we need to do some conversion :-)
3050 */
3051 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
3052 if (This->palette) {
3053 color = ((0xFF000000) |
3054 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
3055 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
3056 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
3057 } else {
3058 color = 0xFF000000;
3059 }
3060 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
3061 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3062 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3063 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3064 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3065 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3066 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3067 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
3068 color = 0xFFFFFFFF;
3069 } else {
3070 color = ((0xFF000000) |
3071 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
3072 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
3073 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
3074 }
3075 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
3076 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
3077 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3078 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3079 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3080 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
3081 } else {
3082 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
3083 return DDERR_INVALIDPARAMS;
3084 }
3085 } else {
3086 ERR("Wrong surface type for BLT override !\n");
3087 return DDERR_INVALIDPARAMS;
3088 }
3089
Lionel Ulmer6fb7ed82003-01-02 19:51:25 +00003090 TRACE(" executing D3D Device override.\n");
Lionel Ulmerf0339d22003-06-13 16:29:18 +00003091
Lionel Ulmerf0339d22003-06-13 16:29:18 +00003092 ENTER_GL();
Lionel Ulmer8daf96c2003-05-20 04:10:22 +00003093
Lionel Ulmerf0339d22003-06-13 16:29:18 +00003094 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
Lionel Ulmer26f51af2003-06-13 23:17:59 +00003095 if (buffer_type == WINE_GL_BUFFER_FRONT)
Lionel Ulmerf0339d22003-06-13 16:29:18 +00003096 glDrawBuffer(GL_FRONT);
3097 else
3098 glDrawBuffer(GL_BACK);
3099
Lionel Ulmer26f51af2003-06-13 23:17:59 +00003100 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
Lionel Ulmerf0339d22003-06-13 16:29:18 +00003101
Lionel Ulmer26f51af2003-06-13 23:17:59 +00003102 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3103 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
Lionel Ulmerf0339d22003-06-13 16:29:18 +00003104 glDrawBuffer(prev_draw);
3105
3106 LEAVE_GL();
3107
3108 return DD_OK;
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003109 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
Lionel Ulmerc203d682003-06-16 19:41:34 +00003110 /* Normal blit without any special case... */
3111 if (src != NULL) {
3112 /* And which has a SRC surface */
3113 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003114
Lionel Ulmerc203d682003-06-16 19:41:34 +00003115 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003116 (src_impl->d3ddevice == This->d3ddevice) &&
3117 ((dwFlags & DDBLT_KEYSRC) == 0)) {
3118 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
Lionel Ulmerc203d682003-06-16 19:41:34 +00003119 D3DRECT src_rect;
3120 int width, height;
Mike McCormack82f9c972005-08-01 09:22:26 +00003121 GLint prev_draw;
Lionel Ulmerc203d682003-06-16 19:41:34 +00003122 WINE_GL_BUFFER_TYPE src_buffer_type;
3123 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
Lionel Ulmer08cc0d12003-07-16 23:28:37 +00003124 BOOLEAN initial;
Lionel Ulmere10a0fd2003-06-16 20:22:46 +00003125 DWORD opt_bitmap;
3126 int x, y;
3127
Lionel Ulmerc203d682003-06-16 19:41:34 +00003128 if (rsrc) {
3129 src_rect.u1.x1 = rsrc->left;
3130 src_rect.u2.y1 = rsrc->top;
3131 src_rect.u3.x2 = rsrc->right;
3132 src_rect.u4.y2 = rsrc->bottom;
3133 } else {
3134 src_rect.u1.x1 = 0;
3135 src_rect.u2.y1 = 0;
3136 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3137 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3138 }
3139
3140 width = src_rect.u3.x2 - src_rect.u1.x1;
3141 height = src_rect.u4.y2 - src_rect.u2.y1;
3142
Lionel Ulmere10a0fd2003-06-16 20:22:46 +00003143 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
3144 (height != (rect.u4.y2 - rect.u2.y1))) {
3145 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
Lionel Ulmerc203d682003-06-16 19:41:34 +00003146 return DDERR_INVALIDPARAMS;
3147 }
3148
3149 /* First check if we BLT from the backbuffer... */
3150 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
3151 src_buffer_type = WINE_GL_BUFFER_BACK;
3152 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3153 src_buffer_type = WINE_GL_BUFFER_FRONT;
3154 } else {
3155 ERR("Unexpected case in direct buffer to buffer copy !\n");
3156 return DDERR_INVALIDPARAMS;
3157 }
3158
3159 TRACE(" using direct buffer to buffer copy.\n");
3160
3161 ENTER_GL();
Lionel Ulmere10a0fd2003-06-16 20:22:46 +00003162
3163 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
3164
3165 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
3166 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3167 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
3168 LEAVE_GL();
3169 return DDERR_INVALIDPARAMS;
3170 }
Lionel Ulmerc203d682003-06-16 19:41:34 +00003171
3172 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3173 if (buffer_type == WINE_GL_BUFFER_FRONT)
3174 glDrawBuffer(GL_FRONT);
3175 else
3176 glDrawBuffer(GL_BACK);
3177
3178 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
3179 glReadBuffer(GL_FRONT);
3180 else
3181 glReadBuffer(GL_BACK);
Lionel Ulmerc203d682003-06-16 19:41:34 +00003182
Lionel Ulmere10a0fd2003-06-16 20:22:46 +00003183 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
3184 And directly re-draws this on the destination buffer. */
3185 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3186 int get_height;
3187
3188 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
3189 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
3190 else
3191 get_height = UNLOCK_TEX_SIZE;
3192
3193 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3194 int get_width;
3195
3196 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
3197 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
3198 else
3199 get_width = UNLOCK_TEX_SIZE;
3200
3201 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
3202 0, UNLOCK_TEX_SIZE - get_height,
3203 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
3204 get_width, get_height);
3205
3206 glBegin(GL_QUADS);
3207 glTexCoord2f(0.0, 0.0);
3208 glVertex3d(rect.u1.x1 + x,
3209 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3210 0.5);
3211 glTexCoord2f(1.0, 0.0);
3212 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3213 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
3214 0.5);
3215 glTexCoord2f(1.0, 1.0);
3216 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
3217 rect.u2.y1 + y,
3218 0.5);
3219 glTexCoord2f(0.0, 1.0);
3220 glVertex3d(rect.u1.x1 + x,
3221 rect.u2.y1 + y,
3222 0.5);
3223 glEnd();
3224 }
3225 }
3226
3227 upload_surface_to_tex_memory_release();
3228 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
Lionel Ulmerc203d682003-06-16 19:41:34 +00003229
3230 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3231 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3232 glDrawBuffer(prev_draw);
3233
3234 LEAVE_GL();
Lionel Ulmere10a0fd2003-06-16 20:22:46 +00003235
3236 return DD_OK;
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003237 } else {
3238 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3239 (this prevents calling glReadPixels) */
3240 D3DRECT src_rect;
3241 int width, height;
Mike McCormack82f9c972005-08-01 09:22:26 +00003242 GLint prev_draw;
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003243 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
Lionel Ulmer08cc0d12003-07-16 23:28:37 +00003244 BOOLEAN initial;
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003245 DWORD opt_bitmap;
3246 int x, y;
3247 double x_stretch, y_stretch;
3248
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003249 if (rsrc) {
3250 src_rect.u1.x1 = rsrc->left;
3251 src_rect.u2.y1 = rsrc->top;
3252 src_rect.u3.x2 = rsrc->right;
3253 src_rect.u4.y2 = rsrc->bottom;
3254 } else {
3255 src_rect.u1.x1 = 0;
3256 src_rect.u2.y1 = 0;
3257 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3258 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3259 }
3260
3261 width = src_rect.u3.x2 - src_rect.u1.x1;
3262 height = src_rect.u4.y2 - src_rect.u2.y1;
3263
3264 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3265 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3266
Francois Gouget87b09062005-01-10 13:29:24 +00003267 TRACE(" using memory to buffer Blt override.\n");
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003268
3269 ENTER_GL();
3270
Lionel Ulmerad912cf2003-07-11 03:50:43 +00003271 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003272
3273 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
Lionel Ulmerad912cf2003-07-11 03:50:43 +00003274 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
Francois Gouget87b09062005-01-10 13:29:24 +00003275 ERR(" unsupported pixel format at memory to buffer Blt override.\n");
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003276 LEAVE_GL();
3277 return DDERR_INVALIDPARAMS;
3278 }
3279
3280 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3281 if (buffer_type == WINE_GL_BUFFER_FRONT)
3282 glDrawBuffer(GL_FRONT);
3283 else
3284 glDrawBuffer(GL_BACK);
3285
Francois Gouget87b09062005-01-10 13:29:24 +00003286 /* Now the serious stuff happens. This is basically the same code as for the memory
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003287 flush to frame buffer ... with stretching and different rectangles added :-) */
3288 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3289 RECT flush_rect;
3290
3291 flush_rect.top = src_rect.u2.y1 + y;
3292 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3293 src_rect.u4.y2 :
3294 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3295
3296 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3297 flush_rect.left = src_rect.u1.x1 + x;
3298 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3299 src_rect.u3.x2 :
3300 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3301
3302 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3303
3304 glBegin(GL_QUADS);
3305 glTexCoord2f(0.0, 0.0);
3306 glVertex3d(rect.u1.x1 + (x * x_stretch),
3307 rect.u2.y1 + (y * y_stretch),
3308 0.5);
3309 glTexCoord2f(1.0, 0.0);
3310 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3311 rect.u2.y1 + (y * y_stretch),
3312 0.5);
3313 glTexCoord2f(1.0, 1.0);
3314 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3315 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3316 0.5);
3317 glTexCoord2f(0.0, 1.0);
3318 glVertex3d(rect.u1.x1 + (x * x_stretch),
3319 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3320 0.5);
3321 glEnd();
3322 }
3323 }
3324
3325 upload_surface_to_tex_memory_release();
Lionel Ulmerad912cf2003-07-11 03:50:43 +00003326 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003327
3328 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3329 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3330 glDrawBuffer(prev_draw);
3331
3332 LEAVE_GL();
3333
3334 return DD_OK;
Lionel Ulmerc203d682003-06-16 19:41:34 +00003335 }
3336 }
Lionel Ulmer6fb7ed82003-01-02 19:51:25 +00003337 }
3338 return DDERR_INVALIDPARAMS;
3339}
3340
3341HRESULT
3342d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3343 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3344 LPRECT rsrc, DWORD trans)
3345{
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003346 RECT rsrc2;
3347 RECT rdst;
3348 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3349 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3350 WINE_GL_BUFFER_TYPE buffer_type;
Mike McCormack82f9c972005-08-01 09:22:26 +00003351 GLint prev_draw;
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003352 DWORD opt_bitmap;
3353 BOOLEAN initial;
3354 int width, height, x, y;
3355
3356 /* Cannot support DSTCOLORKEY blitting... */
3357 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3358
3359 if (rsrc == NULL) {
3360 WARN("rsrc is NULL - getting the whole surface !!\n");
3361 rsrc = &rsrc2;
3362 rsrc->left = rsrc->top = 0;
3363 rsrc->right = src_impl->surface_desc.dwWidth;
3364 rsrc->bottom = src_impl->surface_desc.dwHeight;
3365 } else {
3366 rsrc2 = *rsrc;
3367 rsrc = &rsrc2;
3368 }
3369
3370 rdst.left = dstx;
3371 rdst.top = dsty;
3372 rdst.right = dstx + (rsrc->right - rsrc->left);
3373 if (rdst.right > This->surface_desc.dwWidth) {
3374 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3375 rdst.right = This->surface_desc.dwWidth;
3376 }
3377 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3378 if (rdst.bottom > This->surface_desc.dwHeight) {
3379 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3380 rdst.bottom = This->surface_desc.dwHeight;
3381 }
3382
3383 width = rsrc->right - rsrc->left;
3384 height = rsrc->bottom - rsrc->top;
3385
3386 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3387
Francois Gouget87b09062005-01-10 13:29:24 +00003388 TRACE(" using BltFast memory to frame buffer override.\n");
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003389
3390 ENTER_GL();
3391
3392 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3393
3394 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3395 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3396 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
Francois Gouget87b09062005-01-10 13:29:24 +00003397 ERR(" unsupported pixel format at memory to buffer Blt override.\n");
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003398 LEAVE_GL();
3399 return DDERR_INVALIDPARAMS;
3400 }
3401
3402 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3403 if (buffer_type == WINE_GL_BUFFER_FRONT)
3404 glDrawBuffer(GL_FRONT);
3405 else
3406 glDrawBuffer(GL_BACK);
3407
3408 /* Now the serious stuff happens. This is basically the same code that for the memory
3409 flush to frame buffer but with different rectangles for source and destination :-) */
3410 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3411 RECT flush_rect;
3412
3413 flush_rect.top = rsrc->top + y;
3414 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3415 rsrc->bottom :
3416 (rsrc->top + y + UNLOCK_TEX_SIZE));
3417
3418 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3419 flush_rect.left = rsrc->left + x;
3420 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3421 rsrc->right :
3422 (rsrc->left + x + UNLOCK_TEX_SIZE));
3423
3424 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3425
3426 glBegin(GL_QUADS);
3427 glTexCoord2f(0.0, 0.0);
3428 glVertex3d(rdst.left + x,
3429 rdst.top + y,
3430 0.5);
3431 glTexCoord2f(1.0, 0.0);
3432 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3433 rdst.top + y,
3434 0.5);
3435 glTexCoord2f(1.0, 1.0);
3436 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3437 rdst.top + (y + UNLOCK_TEX_SIZE),
3438 0.5);
3439 glTexCoord2f(0.0, 1.0);
3440 glVertex3d(rdst.left + x,
3441 rdst.top + (y + UNLOCK_TEX_SIZE),
3442 0.5);
3443 glEnd();
3444 }
3445 }
3446
3447 upload_surface_to_tex_memory_release();
3448 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3449
3450 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3451 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3452 glDrawBuffer(prev_draw);
3453
3454 LEAVE_GL();
3455
3456 return DD_OK;
Lionel Ulmer6fb7ed82003-01-02 19:51:25 +00003457}
3458
Lionel Ulmer01149452003-01-03 21:05:38 +00003459void
Lionel Ulmer76beb5b2003-01-05 20:28:35 +00003460d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3461{
3462 GLfloat height, width;
3463 GLfloat trans_mat[16];
Lionel Ulmered883042003-06-04 23:36:48 +00003464
3465 TRACE("(%p)\n", This);
Lionel Ulmer76beb5b2003-01-05 20:28:35 +00003466
3467 width = This->surface->surface_desc.dwWidth;
3468 height = This->surface->surface_desc.dwHeight;
3469
3470 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
Lionel Ulmer2ae876f2004-01-30 22:57:43 +00003471 * to OpenGL screen coordinates (ie the upper left corner is not the same).
3472 */
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00003473 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3474 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
Lionel Ulmer2ae876f2004-01-30 22:57:43 +00003475#if 0
3476 /* It has been checked that in Messiah, which mixes XYZ and XYZRHZ vertex format in the same scene,
3477 * that the Z coordinate needs to be given to GL unchanged.
3478 */
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00003479 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
Lionel Ulmer2ae876f2004-01-30 22:57:43 +00003480#endif
3481 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = 0.0;
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00003482 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3483
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00003484 ENTER_GL();
Lionel Ulmer76beb5b2003-01-05 20:28:35 +00003485 glMatrixMode(GL_MODELVIEW);
3486 glLoadIdentity();
Lionel Ulmer68c3a282003-03-07 20:34:34 +00003487 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3488 Correctness Tips section).
3489
3490 Basically, from what I understood, if the game does not filter the font texture,
3491 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3492 one and we will have strange artifacts (as the rounding and stuff may give different results
3493 for different pixels, ie sometimes take the left pixel, sometimes the right).
3494 */
3495 glTranslatef(0.375, 0.375, 0);
Lionel Ulmer76beb5b2003-01-05 20:28:35 +00003496 glMatrixMode(GL_PROJECTION);
3497 glLoadMatrixf(trans_mat);
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00003498 LEAVE_GL();
Lionel Ulmer76beb5b2003-01-05 20:28:35 +00003499}
3500
3501void
Lionel Ulmer01149452003-01-03 21:05:38 +00003502d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3503 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3504{
Lionel Ulmered883042003-06-04 23:36:48 +00003505 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3506
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00003507 ENTER_GL();
Lionel Ulmer01149452003-01-03 21:05:38 +00003508 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3509 glMatrixMode(GL_MODELVIEW);
3510 glLoadMatrixf((float *) view_mat);
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003511
3512 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3513 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3514 GLint i;
3515 DWORD runner;
3516 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3517 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3518 GLdouble plane[4];
3519
3520 plane[0] = This->clipping_planes[i].plane[0];
3521 plane[1] = This->clipping_planes[i].plane[1];
3522 plane[2] = This->clipping_planes[i].plane[2];
3523 plane[3] = This->clipping_planes[i].plane[3];
3524
3525 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3526 }
3527 }
3528 }
3529 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3530 GLint i;
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003531
Antoine Chavasseb65e7902005-06-07 21:34:40 +00003532 for (i = 0; i < This->max_active_lights; i++ )
3533 {
3534 DWORD dwLightIndex = This->active_lights[i];
3535 if (dwLightIndex != ~0)
3536 {
3537 LPD3DLIGHT7 pLight = &This->light_parameters[dwLightIndex];
3538 switch (pLight->dltType)
3539 {
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003540 case D3DLIGHT_DIRECTIONAL: {
3541 float direction[4];
3542 float cut_off = 180.0;
3543
Antoine Chavasseb65e7902005-06-07 21:34:40 +00003544 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &pLight->dcvAmbient);
3545 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &pLight->dcvDiffuse);
3546 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &pLight->dcvSpecular);
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003547 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3548
Antoine Chavasseb65e7902005-06-07 21:34:40 +00003549 direction[0] = pLight->dvDirection.u1.x;
3550 direction[1] = pLight->dvDirection.u2.y;
3551 direction[2] = pLight->dvDirection.u3.z;
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003552 direction[3] = 0.0;
3553 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3554 } break;
3555
3556 case D3DLIGHT_POINT: {
3557 float position[4];
3558 float cut_off = 180.0;
3559
Antoine Chavasseb65e7902005-06-07 21:34:40 +00003560 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &pLight->dcvAmbient);
3561 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &pLight->dcvDiffuse);
3562 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &pLight->dcvSpecular);
3563 position[0] = pLight->dvPosition.u1.x;
3564 position[1] = pLight->dvPosition.u2.y;
3565 position[2] = pLight->dvPosition.u3.z;
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003566 position[3] = 1.0;
3567 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
Antoine Chavasseb65e7902005-06-07 21:34:40 +00003568 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &pLight->dvAttenuation0);
3569 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &pLight->dvAttenuation1);
3570 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &pLight->dvAttenuation2);
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003571 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3572 } break;
3573
3574 case D3DLIGHT_SPOT: {
3575 float direction[4];
3576 float position[4];
3577 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3578
Antoine Chavasseb65e7902005-06-07 21:34:40 +00003579 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &pLight->dcvAmbient);
3580 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &pLight->dcvDiffuse);
3581 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &pLight->dcvSpecular);
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003582
Antoine Chavasseb65e7902005-06-07 21:34:40 +00003583 direction[0] = pLight->dvDirection.u1.x;
3584 direction[1] = pLight->dvDirection.u2.y;
3585 direction[2] = pLight->dvDirection.u3.z;
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003586 direction[3] = 0.0;
3587 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
Antoine Chavasseb65e7902005-06-07 21:34:40 +00003588 position[0] = pLight->dvPosition.u1.x;
3589 position[1] = pLight->dvPosition.u2.y;
3590 position[2] = pLight->dvPosition.u3.z;
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003591 position[3] = 1.0;
3592 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
Antoine Chavasseb65e7902005-06-07 21:34:40 +00003593 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &pLight->dvAttenuation0);
3594 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &pLight->dvAttenuation1);
3595 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &pLight->dvAttenuation2);
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003596 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
Antoine Chavasseb65e7902005-06-07 21:34:40 +00003597 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &pLight->dvFalloff);
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003598 } break;
3599
3600 default:
3601 /* No warning here as it's already done at light setting */
3602 break;
3603 }
3604 }
3605 }
Antoine Chavasseb65e7902005-06-07 21:34:40 +00003606 }
Lionel Ulmer7b245fa2003-05-20 03:58:01 +00003607
Lionel Ulmer01149452003-01-03 21:05:38 +00003608 glMultMatrixf((float *) world_mat);
3609 }
3610 if ((matrices & PROJMAT_CHANGED) != 0) {
3611 glMatrixMode(GL_PROJECTION);
3612 glLoadMatrixf((float *) proj_mat);
3613 }
Lionel Ulmerfc58c2a2003-06-04 23:34:58 +00003614 LEAVE_GL();
Lionel Ulmer01149452003-01-03 21:05:38 +00003615}
3616
3617void
3618d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3619{
3620 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
Lionel Ulmer11b1b942003-05-20 02:15:24 +00003621 DWORD tex_mat, tex_stage;
Lionel Ulmered883042003-06-04 23:36:48 +00003622
3623 TRACE("(%p,%08lx)\n", This, matrices);
3624
3625 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
Lionel Ulmer11b1b942003-05-20 02:15:24 +00003626 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3627 /* This will force an update of the transform state at the next drawing. */
3628 glThis->transform_state = GL_TRANSFORM_NONE;
3629 }
3630 }
Lionel Ulmerc312ff92003-06-04 21:53:43 +00003631 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3632 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3633 {
3634 ENTER_GL();
3635 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00003636 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
Lionel Ulmerc312ff92003-06-04 21:53:43 +00003637 if (matrices & tex_mat) {
3638 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00003639 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3640
3641 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3642 if (glThis->current_active_tex_unit != unit) {
3643 GL_extensions.glActiveTexture(unit);
3644 glThis->current_active_tex_unit = unit;
3645 }
3646 glMatrixMode(GL_TEXTURE);
Lionel Ulmerc312ff92003-06-04 21:53:43 +00003647 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3648 }
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00003649 This->tex_mat_is_identity[tex_stage] = is_identity;
Lionel Ulmerc312ff92003-06-04 21:53:43 +00003650 } else {
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00003651 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3652 if (glThis->current_active_tex_unit != unit) {
3653 GL_extensions.glActiveTexture(unit);
3654 glThis->current_active_tex_unit = unit;
Lionel Ulmer815118a2003-06-16 01:23:58 +00003655 }
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00003656 glMatrixMode(GL_TEXTURE);
3657 glLoadIdentity();
3658 This->tex_mat_is_identity[tex_stage] = TRUE;
Lionel Ulmer815118a2003-06-16 01:23:58 +00003659 }
Lionel Ulmer11b1b942003-05-20 02:15:24 +00003660 }
Lionel Ulmer11b1b942003-05-20 02:15:24 +00003661 }
3662 }
Lionel Ulmerc312ff92003-06-04 21:53:43 +00003663 LEAVE_GL();
Lionel Ulmer01149452003-01-03 21:05:38 +00003664 }
3665}
Lionel Ulmer608da062002-12-24 01:03:04 +00003666
Lionel Ulmer5f49e782002-11-30 19:06:52 +00003667/* TODO for both these functions :
3668 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3669 by other OpenGL code in D3D
3670 - handle the case where no 'Begin / EndScene' was done between two locks
3671 - handle the rectangles in the unlock too
Lionel Ulmera6e50802002-11-30 19:19:00 +00003672 - handle pitch correctly...
Lionel Ulmer5f49e782002-11-30 19:06:52 +00003673*/
3674static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3675{
Lionel Ulmer783b3232003-05-17 18:41:26 +00003676 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3677 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003678 WINE_GL_BUFFER_TYPE buffer_type;
3679 RECT loc_rect;
Lionel Ulmer783b3232003-05-17 18:41:26 +00003680
3681 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003682 buffer_type = WINE_GL_BUFFER_FRONT;
3683 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3684 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
Lionel Ulmer97f216c2003-05-20 04:27:04 +00003685 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3686 }
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003687 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
Lionel Ulmer783b3232003-05-17 18:41:26 +00003688 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003689 buffer_type = WINE_GL_BUFFER_BACK;
3690 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3691 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
Lionel Ulmer97f216c2003-05-20 04:27:04 +00003692 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3693 }
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003694 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
Lionel Ulmer783b3232003-05-17 18:41:26 +00003695 } else {
3696 ERR("Wrong surface type for locking !\n");
3697 return;
3698 }
Lionel Ulmer449f6b22003-05-11 03:44:53 +00003699
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003700 if (pRect == NULL) {
3701 loc_rect.top = 0;
3702 loc_rect.left = 0;
3703 loc_rect.bottom = This->surface_desc.dwHeight;
3704 loc_rect.right = This->surface_desc.dwWidth;
3705 pRect = &loc_rect;
3706 }
3707
Lionel Ulmer783b3232003-05-17 18:41:26 +00003708 /* Try to acquire the device critical section */
3709 EnterCriticalSection(&(d3d_dev->crit));
3710
Alexandre Julliardebe3c522004-12-09 14:07:59 +00003711 if (gl_d3d_dev->lock_rect_valid[buffer_type]) {
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003712 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3713 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3714 }
3715 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3716
3717 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3718 /* Check if the new rectangle is in the previous one or not.
3719 If it is not, flush first the previous locks on screen.
3720 */
3721 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3722 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3723 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3724 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3725 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3726 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3727 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3728 pRect->left, pRect->top, pRect->right, pRect->bottom,
3729 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3730 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3731 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3732 }
3733 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3734 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3735 }
3736 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3737 } else {
3738 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3739 }
3740
3741 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
Lionel Ulmer783b3232003-05-17 18:41:26 +00003742 /* If the surface is already in memory, no need to do anything here... */
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003743 GLenum buffer_format;
Lionel Ulmer2d275042003-05-19 21:37:50 +00003744 GLenum buffer_color;
Lionel Ulmer783b3232003-05-17 18:41:26 +00003745 int y;
3746 char *dst;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00003747
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003748 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3749 pRect->left, pRect->top, pRect->right, pRect->bottom);
Lionel Ulmer783b3232003-05-17 18:41:26 +00003750
3751 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3752 may only write to the device... But when we will blit it back to the screen, we need
3753 also to blit correctly the parts the application did not overwrite... */
Lionel Ulmered883042003-06-04 23:36:48 +00003754
3755 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3756 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3757 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3758 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3759 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3760 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3761 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003762 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
Lionel Ulmered883042003-06-04 23:36:48 +00003763 buffer_color = GL_RGB;
3764 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3765 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3766 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3767 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003768 buffer_format = GL_UNSIGNED_BYTE;
Lionel Ulmered883042003-06-04 23:36:48 +00003769 buffer_color = GL_RGB;
3770 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3771 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3772 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3773 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003774 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
Lionel Ulmered883042003-06-04 23:36:48 +00003775 buffer_color = GL_BGRA;
3776 } else {
3777 ERR(" unsupported pixel format at device locking.\n");
3778 return;
3779 }
Lionel Ulmer5f49e782002-11-30 19:06:52 +00003780 } else {
Lionel Ulmered883042003-06-04 23:36:48 +00003781 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
Lionel Ulmer5f49e782002-11-30 19:06:52 +00003782 return;
3783 }
Lionel Ulmer783b3232003-05-17 18:41:26 +00003784
Lionel Ulmer8352f1f2003-06-04 23:18:24 +00003785 ENTER_GL();
3786
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003787 if (buffer_type == WINE_GL_BUFFER_FRONT)
Lionel Ulmer8352f1f2003-06-04 23:18:24 +00003788 /* Application wants to lock the front buffer */
3789 glReadBuffer(GL_FRONT);
3790 else
3791 /* Application wants to lock the back buffer */
3792 glReadBuffer(GL_BACK);
3793
Lionel Ulmer783b3232003-05-17 18:41:26 +00003794 dst = ((char *)This->surface_desc.lpSurface) +
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003795 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
Lionel Ulmerc9eb05e2004-07-12 19:47:48 +00003796
3797 if (This->surface_desc.u1.lPitch != (GET_BPP(This->surface_desc) * This->surface_desc.dwWidth)) {
3798 /* Slow-path in case of 'odd' surfaces. This could be fixed using some GL options, but I
3799 * could not be bothered considering the rare cases where it may be useful :-)
3800 */
3801 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3802 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3803 y--) {
3804 glReadPixels(pRect->left, y,
3805 pRect->right - pRect->left, 1,
3806 buffer_color, buffer_format, dst);
3807 dst += This->surface_desc.u1.lPitch;
3808 }
3809 } else {
3810 /* Faster path for surface copy. Note that I can use static variables here as I am
3811 * protected by the OpenGL critical section so this function won't be called by
3812 * two threads at the same time.
3813 */
3814 static char *buffer = NULL;
3815 static int buffer_width = 0;
3816 char *dst2 = dst + ((pRect->bottom - pRect->top) - 1) * This->surface_desc.u1.lPitch;
3817 int current_width = (pRect->right - pRect->left) * GET_BPP(This->surface_desc);
3818
3819 glReadPixels(pRect->left, ((int) This->surface_desc.dwHeight - (int) pRect->bottom),
3820 pRect->right - pRect->left, pRect->bottom - pRect->top,
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003821 buffer_color, buffer_format, dst);
Lionel Ulmerc9eb05e2004-07-12 19:47:48 +00003822
3823 if (current_width > buffer_width) {
3824 if (buffer != NULL) HeapFree(GetProcessHeap(), 0, buffer);
3825 buffer_width = current_width;
3826 buffer = HeapAlloc(GetProcessHeap(), 0, buffer_width);
3827 }
3828 for (y = 0; y < ((pRect->bottom - pRect->top) / 2); y++) {
3829 memcpy(buffer, dst, current_width);
3830 memcpy(dst, dst2, current_width);
3831 memcpy(dst2, buffer, current_width);
3832 dst += This->surface_desc.u1.lPitch;
3833 dst2 -= This->surface_desc.u1.lPitch;
3834 }
Lionel Ulmer783b3232003-05-17 18:41:26 +00003835 }
3836
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003837 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
Lionel Ulmer783b3232003-05-17 18:41:26 +00003838
Lionel Ulmer2d275042003-05-19 21:37:50 +00003839#if 0
3840 /* I keep this code here as it's very useful to debug :-) */
3841 {
3842 static int flush_count = 0;
3843 char buf[128];
3844 FILE *f;
3845
3846 if ((++flush_count % 50) == 0) {
3847 sprintf(buf, "lock_%06d.pnm", flush_count);
3848 f = fopen(buf, "wb");
3849 DDRAW_dump_surface_to_disk(This, f);
3850 }
3851 }
3852#endif
3853
Lionel Ulmer5f49e782002-11-30 19:06:52 +00003854 LEAVE_GL();
3855 }
3856}
3857
Lionel Ulmer97f216c2003-05-20 04:27:04 +00003858static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
Lionel Ulmer783b3232003-05-17 18:41:26 +00003859 RECT loc_rect;
Lionel Ulmer783b3232003-05-17 18:41:26 +00003860 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
Lionel Ulmer783b3232003-05-17 18:41:26 +00003861 int x, y;
Lionel Ulmer08cc0d12003-07-16 23:28:37 +00003862 BOOLEAN initial;
Lionel Ulmer815118a2003-06-16 01:23:58 +00003863 DWORD opt_bitmap;
3864
Lionel Ulmer8352f1f2003-06-04 23:18:24 +00003865 /* Note : no need here to lock the 'device critical section' as we are already protected by
3866 the GL critical section. */
Lionel Ulmer783b3232003-05-17 18:41:26 +00003867
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003868 if (pRect == NULL) {
3869 loc_rect.top = 0;
3870 loc_rect.left = 0;
Lionel Ulmer815118a2003-06-16 01:23:58 +00003871 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3872 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003873 pRect = &loc_rect;
3874 }
3875
3876 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
Lionel Ulmer97140ba2003-06-04 23:26:53 +00003877
Lionel Ulmer815118a2003-06-16 01:23:58 +00003878 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
Lionel Ulmer97140ba2003-06-04 23:26:53 +00003879
3880 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
Lionel Ulmered883042003-06-04 23:36:48 +00003881 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
Lionel Ulmer97140ba2003-06-04 23:26:53 +00003882 ERR(" unsupported pixel format at frame buffer flush.\n");
Lionel Ulmer97140ba2003-06-04 23:26:53 +00003883 return;
3884 }
Lionel Ulmer783b3232003-05-17 18:41:26 +00003885
Lionel Ulmere10a0fd2003-06-16 20:22:46 +00003886 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3887 RECT flush_rect;
3888
3889 flush_rect.top = y;
3890 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
Lionel Ulmer97140ba2003-06-04 23:26:53 +00003891
Lionel Ulmere10a0fd2003-06-16 20:22:46 +00003892 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3893 /* First, upload the texture... */
Lionel Ulmer97140ba2003-06-04 23:26:53 +00003894 flush_rect.left = x;
Lionel Ulmer3dfdfbf2003-06-23 03:34:34 +00003895 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
Lionel Ulmer97140ba2003-06-04 23:26:53 +00003896
3897 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3898
Lionel Ulmer783b3232003-05-17 18:41:26 +00003899 glBegin(GL_QUADS);
Lionel Ulmer783b3232003-05-17 18:41:26 +00003900 glTexCoord2f(0.0, 0.0);
3901 glVertex3d(x, y, 0.5);
3902 glTexCoord2f(1.0, 0.0);
3903 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3904 glTexCoord2f(1.0, 1.0);
3905 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3906 glTexCoord2f(0.0, 1.0);
3907 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3908 glEnd();
3909 }
3910 }
3911
Lionel Ulmer97140ba2003-06-04 23:26:53 +00003912 upload_surface_to_tex_memory_release();
Lionel Ulmer815118a2003-06-16 01:23:58 +00003913 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
Lionel Ulmer783b3232003-05-17 18:41:26 +00003914
Lionel Ulmer2d275042003-05-19 21:37:50 +00003915#if 0
3916 /* I keep this code here as it's very useful to debug :-) */
3917 {
3918 static int flush_count = 0;
3919 char buf[128];
3920 FILE *f;
3921
3922 if ((++flush_count % 50) == 0) {
3923 sprintf(buf, "flush_%06d.pnm", flush_count);
3924 f = fopen(buf, "wb");
3925 DDRAW_dump_surface_to_disk(surf, f);
3926 }
3927 }
3928#endif
Lionel Ulmer783b3232003-05-17 18:41:26 +00003929}
3930
Lionel Ulmer5f49e782002-11-30 19:06:52 +00003931static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3932{
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003933 WINE_GL_BUFFER_TYPE buffer_type;
Lionel Ulmer783b3232003-05-17 18:41:26 +00003934 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
Lionel Ulmerc577c272003-05-20 04:21:46 +00003935 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
Lionel Ulmer783b3232003-05-17 18:41:26 +00003936
3937 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003938 buffer_type = WINE_GL_BUFFER_FRONT;
Lionel Ulmer783b3232003-05-17 18:41:26 +00003939 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003940 buffer_type = WINE_GL_BUFFER_BACK;
Lionel Ulmer783b3232003-05-17 18:41:26 +00003941 } else {
3942 ERR("Wrong surface type for locking !\n");
3943 return;
3944 }
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003945
3946 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3947 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3948 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3949 }
3950 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3951
Lionel Ulmer783b3232003-05-17 18:41:26 +00003952 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
Lionel Ulmerc577c272003-05-20 04:21:46 +00003953 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003954 if (buffer_type == WINE_GL_BUFFER_FRONT) {
Mike McCormack82f9c972005-08-01 09:22:26 +00003955 GLint prev_draw;
Lionel Ulmered883042003-06-04 23:36:48 +00003956
Francois Gouget3bb5b092004-10-22 22:27:51 +00003957 TRACE(" flushing front buffer immediately on screen.\n");
Lionel Ulmered883042003-06-04 23:36:48 +00003958
Lionel Ulmerc577c272003-05-20 04:21:46 +00003959 ENTER_GL();
3960 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3961 glDrawBuffer(GL_FRONT);
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003962 /* Note: we do not use the application provided lock rectangle but our own stored at
3963 lock time. This is because in old D3D versions, the 'lock' parameter did not
3964 exist.
3965 */
3966 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[WINE_GL_BUFFER_FRONT]), gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT]);
Lionel Ulmerc577c272003-05-20 04:21:46 +00003967 glDrawBuffer(prev_draw);
3968 LEAVE_GL();
3969 } else {
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00003970 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
Lionel Ulmerc577c272003-05-20 04:21:46 +00003971 }
Lionel Ulmer783b3232003-05-17 18:41:26 +00003972 }
Lionel Ulmer449f6b22003-05-11 03:44:53 +00003973
3974 /* And 'frees' the device critical section */
Lionel Ulmer783b3232003-05-17 18:41:26 +00003975 LeaveCriticalSection(&(d3d_dev->crit));
Lionel Ulmer5f49e782002-11-30 19:06:52 +00003976}
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00003977
Lionel Ulmer449f6b22003-05-11 03:44:53 +00003978static void
3979apply_texture_state(IDirect3DDeviceImpl *This)
3980{
3981 int stage, state;
3982
3983 /* Initialize texture stages states */
3984 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3985 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
Alexandre Julliardebe3c522004-12-09 14:07:59 +00003986 if (This->state_block.set_flags.texture_stage_state[stage][state]) {
Lionel Ulmer449f6b22003-05-11 03:44:53 +00003987 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3988 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3989 }
3990 }
3991 }
3992}
3993
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00003994HRESULT
Christian Costae64aae02005-02-14 11:09:46 +00003995d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface, int version)
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00003996{
3997 IDirect3DDeviceImpl *object;
3998 IDirect3DDeviceGLImpl *gl_object;
3999 IDirectDrawSurfaceImpl *surf;
4000 HDC device_context;
4001 XVisualInfo *vis;
4002 int num;
Lionel Ulmer11b1b942003-05-20 02:15:24 +00004003 int tex_num;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00004004 XVisualInfo template;
Christian Costa4fc7a842003-01-03 21:08:50 +00004005 GLenum buffer = GL_FRONT;
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00004006 int light;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00004007
4008 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
4009 if (object == NULL) return DDERR_OUTOFMEMORY;
4010
4011 gl_object = (IDirect3DDeviceGLImpl *) object;
4012
4013 object->ref = 1;
4014 object->d3d = d3d;
4015 object->surface = surface;
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00004016 object->set_context = set_context;
Lionel Ulmer26f51af2003-06-13 23:17:59 +00004017 object->clear = d3ddevice_clear_back;
Lionel Ulmer01149452003-01-03 21:05:38 +00004018 object->set_matrices = d3ddevice_set_matrices;
4019 object->matrices_updated = d3ddevice_matrices_updated;
Lionel Ulmer783b3232003-05-17 18:41:26 +00004020 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
Christian Costae64aae02005-02-14 11:09:46 +00004021 object->version = version;
Lionel Ulmer783b3232003-05-17 18:41:26 +00004022
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00004023 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
4024
Lionel Ulmered883042003-06-04 23:36:48 +00004025 InitializeCriticalSection(&(object->crit));
4026
4027 TRACE(" device critical section : %p\n", &(object->crit));
Lionel Ulmerb6ddd8c2003-11-11 00:31:16 +00004028
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00004029 device_context = GetDC(surface->ddraw_owner->window);
4030 gl_object->display = get_display(device_context);
4031 gl_object->drawable = get_drawable(device_context);
4032 ReleaseDC(surface->ddraw_owner->window,device_context);
Lionel Ulmer5f49e782002-11-30 19:06:52 +00004033
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00004034 ENTER_GL();
4035 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
4036 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
4037 if (vis == NULL) {
4038 HeapFree(GetProcessHeap(), 0, object);
4039 ERR("No visual found !\n");
4040 LEAVE_GL();
4041 return DDERR_INVALIDPARAMS;
4042 } else {
4043 TRACE(" visual found\n");
4044 }
4045
4046 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
4047 NULL, GL_TRUE);
4048
4049 if (gl_object->gl_context == NULL) {
4050 HeapFree(GetProcessHeap(), 0, object);
4051 ERR("Error in context creation !\n");
4052 LEAVE_GL();
4053 return DDERR_INVALIDPARAMS;
4054 } else {
4055 TRACE(" context created (%p)\n", gl_object->gl_context);
4056 }
4057
4058 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
4059 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
4060 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
Lionel Ulmer783b3232003-05-17 18:41:26 +00004061 surf->aux_ctx = (LPVOID) object;
Lionel Ulmer5f49e782002-11-30 19:06:52 +00004062 surf->aux_data = (LPVOID) gl_object->drawable;
4063 surf->aux_flip = opengl_flip;
4064 buffer = GL_BACK;
Christian Costab47c14a2002-10-17 01:20:52 +00004065 break;
4066 }
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00004067 }
Lionel Ulmer5f49e782002-11-30 19:06:52 +00004068 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
4069 if (surf == NULL) {
4070 TRACE(" no double buffering : drawing on the front buffer\n");
4071 buffer = GL_FRONT;
4072 }
4073
Lionel Ulmer449f6b22003-05-11 03:44:53 +00004074 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
4075 IDirectDrawSurfaceImpl *surf2;
4076 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
4077 for (; surf2 != NULL; surf2 = surf2->next_attached) {
4078 TRACE(" checking surface %p :", surf2);
4079 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
4080 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
4081 /* Override the Lock / Unlock function for all these surfaces */
Lionel Ulmer783b3232003-05-17 18:41:26 +00004082 surf2->lock_update_prev = surf2->lock_update;
Lionel Ulmer449f6b22003-05-11 03:44:53 +00004083 surf2->lock_update = d3ddevice_lock_update;
Lionel Ulmer783b3232003-05-17 18:41:26 +00004084 surf2->unlock_update_prev = surf2->unlock_update;
Lionel Ulmer449f6b22003-05-11 03:44:53 +00004085 surf2->unlock_update = d3ddevice_unlock_update;
4086 /* And install also the blt / bltfast overrides */
4087 surf2->aux_blt = d3ddevice_blt;
4088 surf2->aux_bltfast = d3ddevice_bltfast;
4089
Francois Gouget87b09062005-01-10 13:29:24 +00004090 TRACE(" overriding direct surface access.\n");
Lionel Ulmer449f6b22003-05-11 03:44:53 +00004091 } else {
Francois Gouget87b09062005-01-10 13:29:24 +00004092 TRACE(" no override.\n");
Lionel Ulmer449f6b22003-05-11 03:44:53 +00004093 }
4094 surf2->d3ddevice = object;
Lionel Ulmer5f49e782002-11-30 19:06:52 +00004095 }
Lionel Ulmer5f49e782002-11-30 19:06:52 +00004096 }
Christian Costa4fc7a842003-01-03 21:08:50 +00004097
Lionel Ulmerd70a2c02003-01-02 20:01:54 +00004098 /* Set the various light parameters */
Antoine Chavasseb65e7902005-06-07 21:34:40 +00004099 object->num_set_lights = 0;
4100 object->max_active_lights = opengl_device_caps.dwMaxActiveLights;
4101 object->light_parameters = NULL;
4102 object->active_lights = HeapAlloc(GetProcessHeap(), 0,
Marcus Meissner1e3dda62005-07-03 11:21:32 +00004103 object->max_active_lights * sizeof(object->active_lights[0]));
Antoine Chavasseb65e7902005-06-07 21:34:40 +00004104 /* Fill the active light array with ~0, which is used to indicate an
4105 invalid light index. We don't use 0, because it's a valid light index. */
4106 for (light=0; light < object->max_active_lights; light++)
4107 object->active_lights[light] = ~0;
4108
Lionel Ulmerdfddf922002-12-16 22:39:09 +00004109
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00004110 /* Allocate memory for the matrices */
Jakob Eriksson9ed61de2005-03-24 21:01:35 +00004111 object->world_mat = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4112 object->view_mat = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
4113 object->proj_mat = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
Lionel Ulmereb6e8302003-01-02 19:53:43 +00004114 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
4115 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
4116 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
Lionel Ulmer11b1b942003-05-20 02:15:24 +00004117 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
Jakob Eriksson9ed61de2005-03-24 21:01:35 +00004118 object->tex_mat[tex_num] = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
Lionel Ulmer11b1b942003-05-20 02:15:24 +00004119 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
Lionel Ulmer815118a2003-06-16 01:23:58 +00004120 object->tex_mat_is_identity[tex_num] = TRUE;
Lionel Ulmer11b1b942003-05-20 02:15:24 +00004121 }
4122
Lionel Ulmer1279d9a2003-05-04 02:24:03 +00004123 /* Initialisation */
4124 TRACE(" setting current context\n");
Lionel Ulmer1279d9a2003-05-04 02:24:03 +00004125 object->set_context(object);
Lionel Ulmer1279d9a2003-05-04 02:24:03 +00004126 TRACE(" current context set\n");
4127
Christoph Frick7f4cb062003-01-07 19:42:26 +00004128 /* allocate the clipping planes */
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004129 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
Jakob Eriksson9ed61de2005-03-24 21:01:35 +00004130 object->clipping_planes = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
Christoph Frick7f4cb062003-01-07 19:42:26 +00004131
Christian Costaf21887f2003-02-12 01:11:17 +00004132 glHint(GL_FOG_HINT,GL_NICEST);
Lionel Ulmer815118a2003-06-16 01:23:58 +00004133
4134 /* Initialize the various GL contexts to be in sync with what we store locally */
4135 glClearDepth(0.0);
4136 glClearStencil(0);
Marcus Meissner10ad97c2000-04-09 14:30:50 +00004137 glClearColor(0.0, 0.0, 0.0, 0.0);
Lionel Ulmer815118a2003-06-16 01:23:58 +00004138 glDepthMask(GL_TRUE);
4139 gl_object->depth_mask = TRUE;
4140 glEnable(GL_DEPTH_TEST);
4141 gl_object->depth_test = TRUE;
4142 glDisable(GL_ALPHA_TEST);
4143 glDisable(GL_STENCIL_TEST);
4144 glDisable(GL_CULL_FACE);
4145 glDisable(GL_LIGHTING);
4146 glDisable(GL_BLEND);
4147 glDisable(GL_FOG);
4148 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
4149 gl_object->current_tex_env = GL_REPLACE;
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00004150 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
4151 if (GL_extensions.glActiveTexture != NULL) {
4152 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
4153 }
Lionel Ulmerb6ddd8c2003-11-11 00:31:16 +00004154 gl_object->current_alpha_test_ref = 0.0;
4155 gl_object->current_alpha_test_func = GL_ALWAYS;
4156 glAlphaFunc(GL_ALWAYS, 0.0);
Lionel Ulmer815118a2003-06-16 01:23:58 +00004157
Lionel Ulmer5f49e782002-11-30 19:06:52 +00004158 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
4159 glDrawBuffer(buffer);
Lionel Ulmera6e50802002-11-30 19:19:00 +00004160 glReadBuffer(buffer);
Lionel Ulmer5f49e782002-11-30 19:06:52 +00004161 /* 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 +00004162 LEAVE_GL();
Lionel Ulmera8cc5f52000-07-16 14:40:35 +00004163
Lionel Ulmer068fa5d2003-06-04 23:43:29 +00004164 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
4165 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
Lionel Ulmer783b3232003-05-17 18:41:26 +00004166
Christian Costa774c5f72002-11-24 22:14:40 +00004167 /* fill_device_capabilities(d3d->ddraw); */
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00004168
4169 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
4170 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
4171 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
4172 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
Vincent BĂ©ron9a624912002-05-31 23:06:46 +00004173
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00004174 *obj = object;
4175
4176 TRACE(" creating implementation at %p.\n", *obj);
Lionel Ulmer8cd26092003-01-02 19:39:57 +00004177
4178 /* And finally warn D3D that this device is now present */
Lionel Ulmer4aba2822003-06-04 23:31:39 +00004179 object->d3d->d3d_added_device(object->d3d, object);
Lionel Ulmer07f12692003-01-05 01:04:55 +00004180
Christian Costae64aae02005-02-14 11:09:46 +00004181 InitDefaultStateBlock(&object->state_block, object->version);
Lionel Ulmer449f6b22003-05-11 03:44:53 +00004182 /* Apply default render state and texture stage state values */
Lionel Ulmer1213c172003-01-07 23:08:31 +00004183 apply_render_state(object, &object->state_block);
Lionel Ulmer449f6b22003-05-11 03:44:53 +00004184 apply_texture_state(object);
Lionel Ulmer07f12692003-01-05 01:04:55 +00004185
Lionel Ulmer6238f9a2003-02-12 21:26:05 +00004186 /* And fill the fog table with the default fog value */
4187 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
4188
Lionel Ulmer43c3dc42002-11-21 21:04:16 +00004189 return DD_OK;
Marcus Meissner10ad97c2000-04-09 14:30:50 +00004190}
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004191
4192static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
4193{
4194 pc->dwSize = sizeof(*pc);
4195 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
Lionel Ulmer4bc97ce2003-08-02 00:41:03 +00004196 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004197 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
Lionel Ulmer50fbe732003-08-05 19:18:19 +00004198 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
4199 D3DPRASTERCAPS_ZFOG;
Alexandre Julliardebe3c522004-12-09 14:07:59 +00004200 if (GL_extensions.mipmap_lodbias) {
Lionel Ulmer50fbe732003-08-05 19:18:19 +00004201 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
4202 }
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004203 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4204 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4205 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
4206 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4207 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4208 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
4209 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
4210 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
4211 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
4212 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
4213 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
4214 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
4215 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
4216 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
4217 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
Lionel Ulmer4bc97ce2003-08-02 00:41:03 +00004218 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
4219 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
4220 D3DPTFILTERCAPS_MIPFPOINT;
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004221 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
4222 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
4223 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
Alexandre Julliardebe3c522004-12-09 14:07:59 +00004224 if (GL_extensions.mirrored_repeat) {
Lionel Ulmer1d45ab42003-08-05 18:28:07 +00004225 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
4226 }
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004227 pc->dwStippleWidth = 32;
4228 pc->dwStippleHeight = 32;
4229}
4230
4231static void fill_caps(void)
4232{
4233 GLint max_clip_planes;
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00004234 GLint depth_bits;
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004235
4236 /* Fill first all the fields with default values which will be overriden later on with
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00004237 correct ones from the GL code
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004238 */
4239 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
4240 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
4241 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
4242 /* D3D 7 capabilities */
Christian Costa7e51de62004-03-20 02:33:17 +00004243 D3DDEVCAPS_DRAWPRIMITIVES2 /*| D3DDEVCAPS_HWTRANSFORMANDLIGHT*/ | D3DDEVCAPS_HWRASTERIZATION | D3DDEVCAPS_DRAWPRIMITIVES2EX;
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004244 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
4245 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
4246 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004247 opengl_device_caps.dwMinTextureWidth = 1;
4248 opengl_device_caps.dwMinTextureHeight = 1;
4249 opengl_device_caps.dwMaxTextureWidth = 1024;
4250 opengl_device_caps.dwMaxTextureHeight = 1024;
4251 opengl_device_caps.dwMaxTextureRepeat = 16;
4252 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
4253 opengl_device_caps.dwMaxAnisotropy = 0;
4254 opengl_device_caps.dvGuardBandLeft = 0.0;
4255 opengl_device_caps.dvGuardBandRight = 0.0;
4256 opengl_device_caps.dvGuardBandTop = 0.0;
4257 opengl_device_caps.dvGuardBandBottom = 0.0;
4258 opengl_device_caps.dvExtentsAdjust = 0.0;
4259 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
4260 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00004261 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
4262 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
4263 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
4264 if (GL_extensions.max_texture_units != 0) {
4265 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
4266 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
4267 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
4268 } else {
4269 opengl_device_caps.wMaxTextureBlendStages = 1;
4270 opengl_device_caps.wMaxSimultaneousTextures = 1;
4271 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
4272 }
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004273 opengl_device_caps.dwMaxActiveLights = 16;
4274 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
4275 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
4276 opengl_device_caps.wMaxUserClipPlanes = 1;
4277 opengl_device_caps.wMaxVertexBlendMatrices = 0;
4278 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
4279 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
4280 opengl_device_caps.dwReserved1 = 0;
4281 opengl_device_caps.dwReserved2 = 0;
4282 opengl_device_caps.dwReserved3 = 0;
4283 opengl_device_caps.dwReserved4 = 0;
4284
Francois Gouget87b09062005-01-10 13:29:24 +00004285 /* And now some GL overrides :-) */
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004286 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
4287 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
4288 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
4289 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
4290
4291 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4292 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4293
4294 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4295 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4296 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00004297
4298 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4299 TRACE(": Z bits = %d\n", depth_bits);
4300 switch (depth_bits) {
4301 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
Christian Costa4bf5d022003-10-16 19:08:33 +00004302 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24; break;
4303 case 32:
4304 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
Lionel Ulmer8c1c2762003-09-15 20:00:03 +00004305 }
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004306}
4307
4308BOOL
4309d3ddevice_init_at_startup(void *gl_handle)
4310{
4311 XVisualInfo template;
4312 XVisualInfo *vis;
4313 HDC device_context;
4314 Display *display;
4315 Visual *visual;
4316 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4317 XWindowAttributes win_attr;
4318 GLXContext gl_context;
4319 int num;
Lionel Ulmer1d45ab42003-08-05 18:28:07 +00004320 const char *glExtensions;
4321 const char *glVersion;
4322 const char *glXExtensions = NULL;
4323 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
Lionel Ulmera39afdd2003-11-11 20:38:20 +00004324 int major, minor, patch, num_parsed;
Lionel Ulmer1d45ab42003-08-05 18:28:07 +00004325
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004326 TRACE("Initializing GL...\n");
Dmitry Timoshkov627260f2004-12-06 16:21:27 +00004327
4328 if (!drawable)
4329 {
4330 WARN("x11drv not loaded - D3D support disabled!\n");
4331 return FALSE;
4332 }
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004333
4334 /* Get a default rendering context to have the 'caps' function query some info from GL */
4335 device_context = GetDC(0);
4336 display = get_display(device_context);
4337 ReleaseDC(0, device_context);
4338
4339 ENTER_GL();
4340 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4341 visual = win_attr.visual;
4342 } else {
4343 visual = DefaultVisual(display, DefaultScreen(display));
4344 }
4345 template.visualid = XVisualIDFromVisual(visual);
4346 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4347 if (vis == NULL) {
4348 LEAVE_GL();
4349 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4350 return FALSE;
4351 }
4352 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
Saulius Krasuckas328d3102005-08-22 18:58:27 +00004353 XFree(vis);
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004354
4355 if (gl_context == NULL) {
4356 LEAVE_GL();
4357 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4358 return FALSE;
4359 }
4360 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4361 glXDestroyContext(display, gl_context);
4362 LEAVE_GL();
4363 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4364 return FALSE;
4365 }
4366
Lionel Ulmer1d45ab42003-08-05 18:28:07 +00004367 /* Then, query all extensions */
Lionel Ulmer266223d2003-12-30 19:13:32 +00004368 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display)); /* Note: not used right now but will for PBuffers */
Lionel Ulmer1d45ab42003-08-05 18:28:07 +00004369 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4370 glVersion = (const char *) glGetString(GL_VERSION);
Lionel Ulmer266223d2003-12-30 19:13:32 +00004371 if (gl_handle != NULL) {
Lionel Ulmer1d45ab42003-08-05 18:28:07 +00004372 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4373 }
4374
4375 /* Parse the GL version string */
Lionel Ulmera39afdd2003-11-11 20:38:20 +00004376 num_parsed = sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4377 if (num_parsed == 1) {
4378 minor = 0;
4379 patch = 0;
4380 } else if (num_parsed == 2) {
4381 patch = 0;
4382 }
Lionel Ulmer1d45ab42003-08-05 18:28:07 +00004383 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4384
4385 /* And starts to fill the extension context properly */
4386 memset(&GL_extensions, 0, sizeof(GL_extensions));
4387 TRACE("GL supports following extensions used by Wine :\n");
4388
4389 /* Mirrored Repeat extension :
4390 - GL_ARB_texture_mirrored_repeat
4391 - GL_IBM_texture_mirrored_repeat
4392 - GL >= 1.4
4393 */
4394 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4395 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00004396 (major > 1) ||
4397 ((major == 1) && (minor >= 4))) {
Lionel Ulmer1d45ab42003-08-05 18:28:07 +00004398 TRACE(" - mirrored repeat\n");
4399 GL_extensions.mirrored_repeat = TRUE;
4400 }
Lionel Ulmer50fbe732003-08-05 19:18:19 +00004401
4402 /* Texture LOD Bias :
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00004403 - GL_EXT_texture_lod_bias
Lionel Ulmer50fbe732003-08-05 19:18:19 +00004404 */
4405 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4406 TRACE(" - texture lod bias\n");
4407 GL_extensions.mipmap_lodbias = TRUE;
4408 }
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00004409
4410 /* For all subsequent extensions, we need glXGetProcAddress */
4411 if (pglXGetProcAddressARB != NULL) {
4412 /* Multi-texturing :
4413 - GL_ARB_multitexture
4414 - GL >= 1.2.1
4415 */
4416 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4417 (major > 1) ||
4418 ((major == 1) && (minor > 2)) ||
4419 ((major == 1) && (minor == 2) && (patch >= 1))) {
4420 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4421 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4422 /* We query the ARB version to be the most portable we can... */
Mike McCormackb814be92005-08-11 10:57:47 +00004423 GL_extensions.glActiveTexture = pglXGetProcAddressARB( (const GLubyte *) "glActiveTextureARB");
4424 GL_extensions.glMultiTexCoord[0] = pglXGetProcAddressARB( (const GLubyte *) "glMultiTexCoord1fvARB");
4425 GL_extensions.glMultiTexCoord[1] = pglXGetProcAddressARB( (const GLubyte *) "glMultiTexCoord2fvARB");
4426 GL_extensions.glMultiTexCoord[2] = pglXGetProcAddressARB( (const GLubyte *) "glMultiTexCoord3fvARB");
4427 GL_extensions.glMultiTexCoord[3] = pglXGetProcAddressARB( (const GLubyte *) "glMultiTexCoord4fvARB");
4428 GL_extensions.glClientActiveTexture = pglXGetProcAddressARB( (const GLubyte *) "glClientActiveTextureARB");
Lionel Ulmer78e95192005-06-12 10:43:11 +00004429 } else {
4430 GL_extensions.max_texture_units = 0;
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00004431 }
Christian Costaeac96b52004-07-30 18:54:32 +00004432
4433 if (strstr(glExtensions, "GL_EXT_texture_compression_s3tc")) {
4434 TRACE(" - S3TC compression supported\n");
4435 GL_extensions.s3tc_compressed_texture = TRUE;
Mike McCormackb814be92005-08-11 10:57:47 +00004436 GL_extensions.glCompressedTexImage2D = pglXGetProcAddressARB( (const GLubyte *) "glCompressedTexImage2DARB");
4437 GL_extensions.glCompressedTexSubImage2D = pglXGetProcAddressARB( (const GLubyte *) "glCompressedTexSubImage2DARB");
Christian Costaeac96b52004-07-30 18:54:32 +00004438 }
Lionel Ulmer4d8d0f02003-08-18 19:55:11 +00004439 }
Lionel Ulmerd1291ba2003-07-28 19:05:49 +00004440
4441 /* Fill the D3D capabilities according to what GL tells us... */
4442 fill_caps();
4443
4444 /* And frees this now-useless context */
4445 glXMakeCurrent(display, None, NULL);
4446 glXDestroyContext(display, gl_context);
4447 LEAVE_GL();
4448
4449 return TRUE;
4450}