Fix some stupid bug with missing braces.
[wine.git] / dlls / ddraw / d3ddevice / mesa.c
blob12539ad43f4d44219f9c48d6a683941fce79d040
1 /* Direct3D Device
2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
5 * Wine supports.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdarg.h>
26 #include <string.h>
27 #include <math.h>
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winerror.h"
34 #include "objbase.h"
35 #include "wingdi.h"
36 #include "ddraw.h"
37 #include "d3d.h"
38 #include "wine/debug.h"
39 #include "wine/library.h"
41 #include "mesa_private.h"
42 #include "main.h"
44 WINE_DEFAULT_DEBUG_CHANNEL(ddraw);
45 WINE_DECLARE_DEBUG_CHANNEL(ddraw_geom);
46 WINE_DECLARE_DEBUG_CHANNEL(ddraw_fps);
48 /* x11drv GDI escapes */
49 #define X11DRV_ESCAPE 6789
50 enum x11drv_escape_codes
52 X11DRV_GET_DISPLAY, /* get X11 display for a DC */
53 X11DRV_GET_DRAWABLE, /* get current drawable for a DC */
54 X11DRV_GET_FONT, /* get current X font for a DC */
57 /* They are non-static as they are used by Direct3D in the creation function */
58 const GUID IID_D3DDEVICE_OpenGL = {
59 0x31416d44,
60 0x86ae,
61 0x11d2,
62 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
65 const float id_mat[16] = {
66 1.0, 0.0, 0.0, 0.0,
67 0.0, 1.0, 0.0, 0.0,
68 0.0, 0.0, 1.0, 0.0,
69 0.0, 0.0, 0.0, 1.0
72 /* This is filled at DLL loading time */
73 static D3DDEVICEDESC7 opengl_device_caps;
74 GL_EXTENSIONS_LIST GL_extensions;
76 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
77 D3DPRIMITIVETYPE d3dptPrimitiveType,
78 DWORD d3dvtVertexType,
79 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
80 DWORD dwVertexCount,
81 LPWORD dwIndices,
82 DWORD dwIndexCount,
83 DWORD dwFlags) ;
85 static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
87 /* retrieve the X display to use on a given DC */
88 inline static Display *get_display( HDC hdc )
90 Display *display;
91 enum x11drv_escape_codes escape = X11DRV_GET_DISPLAY;
93 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
94 sizeof(display), (LPSTR)&display )) display = NULL;
96 return display;
99 #define UNLOCK_TEX_SIZE 256
101 #define DEPTH_RANGE_BIT (0x00000001 << 0)
102 #define VIEWPORT_BIT (0x00000001 << 1)
104 static DWORD d3ddevice_set_state_for_flush(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, BOOLEAN use_alpha, BOOLEAN *initial) {
105 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
106 DWORD opt_bitmap = 0x00000000;
108 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE0_WINE) {
109 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
110 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE0_WINE;
112 if (gl_d3d_dev->unlock_tex == 0) {
113 glGenTextures(1, &gl_d3d_dev->unlock_tex);
114 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
115 *initial = TRUE;
116 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
117 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
118 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
119 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
120 } else {
121 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
122 *initial = FALSE;
124 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
125 glMatrixMode(GL_TEXTURE);
126 glLoadIdentity();
129 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
130 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
131 d3ddevice_set_ortho(d3d_dev);
134 if (gl_d3d_dev->depth_test != FALSE) glDisable(GL_DEPTH_TEST);
135 if ((gl_d3d_dev->current_bound_texture[0] == NULL) ||
136 (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE))
137 glEnable(GL_TEXTURE_2D);
138 if (gl_d3d_dev->current_bound_texture[1] != NULL) {
139 if (gl_d3d_dev->current_active_tex_unit != GL_TEXTURE1_WINE) {
140 GL_extensions.glActiveTexture(GL_TEXTURE1_WINE);
141 gl_d3d_dev->current_active_tex_unit = GL_TEXTURE1_WINE;
143 /* 'unbound' texture level 1 in that case to disable multi-texturing */
144 glBindTexture(GL_TEXTURE_2D, 0);
145 glDisable(GL_TEXTURE_2D);
147 glEnable(GL_SCISSOR_TEST);
148 if ((d3d_dev->active_viewport.dvMinZ != 0.0) ||
149 (d3d_dev->active_viewport.dvMaxZ != 1.0)) {
150 glDepthRange(0.0, 1.0);
151 opt_bitmap |= DEPTH_RANGE_BIT;
153 if ((d3d_dev->active_viewport.dwX != 0) ||
154 (d3d_dev->active_viewport.dwY != 0) ||
155 (d3d_dev->active_viewport.dwWidth != d3d_dev->surface->surface_desc.dwWidth) ||
156 (d3d_dev->active_viewport.dwHeight != d3d_dev->surface->surface_desc.dwHeight)) {
157 glViewport(0, 0, d3d_dev->surface->surface_desc.dwWidth, d3d_dev->surface->surface_desc.dwHeight);
158 opt_bitmap |= VIEWPORT_BIT;
160 glScissor(pRect->left, d3d_dev->surface->surface_desc.dwHeight - pRect->bottom,
161 pRect->right - pRect->left, pRect->bottom - pRect->top);
162 if (gl_d3d_dev->lighting != FALSE) glDisable(GL_LIGHTING);
163 if (gl_d3d_dev->cull_face != FALSE) glDisable(GL_CULL_FACE);
164 if (use_alpha) {
165 if (gl_d3d_dev->alpha_test == FALSE) glEnable(GL_ALPHA_TEST);
166 if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||
167 ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {
168 glAlphaFunc(GL_GREATER, 0.0);
170 } else {
171 if (gl_d3d_dev->alpha_test != FALSE) glDisable(GL_ALPHA_TEST);
173 if (gl_d3d_dev->stencil_test != FALSE) glDisable(GL_STENCIL_TEST);
174 if (gl_d3d_dev->blending != FALSE) glDisable(GL_BLEND);
175 if (gl_d3d_dev->fogging != FALSE) glDisable(GL_FOG);
176 if (gl_d3d_dev->current_tex_env != GL_REPLACE)
177 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
179 return opt_bitmap;
182 static void d3ddevice_restore_state_after_flush(IDirect3DDeviceImpl *d3d_dev, DWORD opt_bitmap, BOOLEAN use_alpha) {
183 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
185 /* And restore all the various states modified by this code */
186 if (gl_d3d_dev->depth_test != 0) glEnable(GL_DEPTH_TEST);
187 if (gl_d3d_dev->lighting != 0) glEnable(GL_LIGHTING);
188 if ((gl_d3d_dev->alpha_test != 0) && (use_alpha == 0))
189 glEnable(GL_ALPHA_TEST);
190 else if ((gl_d3d_dev->alpha_test == 0) && (use_alpha != 0))
191 glDisable(GL_ALPHA_TEST);
192 if (use_alpha) {
193 if (((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) != 0x00) ||
194 ((d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]) != D3DCMP_GREATER)) {
195 glAlphaFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAFUNC - 1]),
196 (d3d_dev->state_block.render_state[D3DRENDERSTATE_ALPHAREF - 1] & 0x000000FF) / 255.0);
199 if (gl_d3d_dev->stencil_test != 0) glEnable(GL_STENCIL_TEST);
200 if (gl_d3d_dev->cull_face != 0) glEnable(GL_CULL_FACE);
201 if (gl_d3d_dev->blending != 0) glEnable(GL_BLEND);
202 if (gl_d3d_dev->fogging != 0) glEnable(GL_FOG);
203 glDisable(GL_SCISSOR_TEST);
204 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, gl_d3d_dev->current_tex_env);
205 if (opt_bitmap & DEPTH_RANGE_BIT) {
206 glDepthRange(d3d_dev->active_viewport.dvMinZ, d3d_dev->active_viewport.dvMaxZ);
208 if (opt_bitmap & VIEWPORT_BIT) {
209 glViewport(d3d_dev->active_viewport.dwX,
210 d3d_dev->surface->surface_desc.dwHeight - (d3d_dev->active_viewport.dwHeight + d3d_dev->active_viewport.dwY),
211 d3d_dev->active_viewport.dwWidth, d3d_dev->active_viewport.dwHeight);
213 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
214 d3d_dev->matrices_updated(d3d_dev, TEXMAT0_CHANGED);
217 /* This is a hack to prevent querying the current texture from GL. Basically, at the next
218 DrawPrimitive call, this will bind the correct texture to this stage. */
219 gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
220 gl_d3d_dev->current_bound_texture[1] = (IDirectDrawSurfaceImpl *) 0x00000000;
221 if (d3d_dev->state_block.texture_stage_state[0][D3DTSS_COLOROP - 1] == D3DTOP_DISABLE) glDisable(GL_TEXTURE_2D);
224 /* retrieve the X drawable to use on a given DC */
225 inline static Drawable get_drawable( HDC hdc )
227 Drawable drawable;
228 enum x11drv_escape_codes escape = X11DRV_GET_DRAWABLE;
230 if (!ExtEscape( hdc, X11DRV_ESCAPE, sizeof(escape), (LPCSTR)&escape,
231 sizeof(drawable), (LPSTR)&drawable )) drawable = 0;
233 return drawable;
236 /* This is unnecessarely complicated :-) */
237 #define MEASUREMENT_WINDOW 5
238 #define NUMBER_OF_WINDOWS 10
240 static LONGLONG perf_freq;
241 static LONGLONG perf_storage[NUMBER_OF_WINDOWS];
242 static LONGLONG prev_time = 0;
243 static unsigned int current_window;
244 static unsigned int measurements_in_window;
245 static unsigned int valid_windows;
247 static BOOL opengl_flip( LPVOID dev, LPVOID drawable)
249 IDirect3DDeviceImpl *d3d_dev = (IDirect3DDeviceImpl *) dev;
250 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) dev;
252 TRACE("(%p, %ld)\n", gl_d3d_dev->display,(Drawable)drawable);
253 ENTER_GL();
254 if (gl_d3d_dev->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
255 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]);
257 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
258 gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
259 glXSwapBuffers(gl_d3d_dev->display, (Drawable)drawable);
260 LEAVE_GL();
262 if (TRACE_ON(ddraw_fps)) {
263 LONGLONG current_time;
264 LONGLONG frame_duration;
265 QueryPerformanceCounter((LARGE_INTEGER *) &current_time);
267 if (prev_time != 0) {
268 LONGLONG total_time = 0;
269 int tot_meas;
271 frame_duration = current_time - prev_time;
272 prev_time = current_time;
274 perf_storage[current_window] += frame_duration;
275 measurements_in_window++;
277 if (measurements_in_window >= MEASUREMENT_WINDOW) {
278 current_window++;
279 valid_windows++;
281 if (valid_windows < NUMBER_OF_WINDOWS) {
282 int i;
283 tot_meas = valid_windows * MEASUREMENT_WINDOW;
284 for (i = 0; i < valid_windows; i++) {
285 total_time += perf_storage[i];
287 } else {
288 int i;
289 tot_meas = NUMBER_OF_WINDOWS * MEASUREMENT_WINDOW;
290 for (i = 0; i < NUMBER_OF_WINDOWS; i++) {
291 total_time += perf_storage[i];
295 TRACE_(ddraw_fps)(" %9.5f\n", (double) (perf_freq * tot_meas) / (double) total_time);
297 if (current_window >= NUMBER_OF_WINDOWS) {
298 current_window = 0;
300 perf_storage[current_window] = 0;
301 measurements_in_window = 0;
303 } else {
304 prev_time = current_time;
305 memset(perf_storage, 0, sizeof(perf_storage));
306 current_window = 0;
307 valid_windows = 0;
308 measurements_in_window = 0;
309 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
313 return TRUE;
317 /*******************************************************************************
318 * OpenGL static functions
320 static void set_context(IDirect3DDeviceImpl* This)
322 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
324 TRACE("glxMakeCurrent %p, %ld, %p\n",glThis->display,glThis->drawable, glThis->gl_context);
325 ENTER_GL();
326 if (glXMakeCurrent(glThis->display, glThis->drawable, glThis->gl_context) == False) {
327 ERR("Error in setting current context (context %p drawable %ld)!\n",
328 glThis->gl_context, glThis->drawable);
330 LEAVE_GL();
333 static void fill_opengl_caps(D3DDEVICEDESC *d1)
335 d1->dwSize = sizeof(*d1);
336 d1->dwFlags = D3DDD_COLORMODEL | D3DDD_DEVCAPS | D3DDD_TRANSFORMCAPS | D3DDD_BCLIPPING | D3DDD_LIGHTINGCAPS |
337 D3DDD_LINECAPS | D3DDD_TRICAPS | D3DDD_DEVICERENDERBITDEPTH | D3DDD_DEVICEZBUFFERBITDEPTH |
338 D3DDD_MAXBUFFERSIZE | D3DDD_MAXVERTEXCOUNT;
339 d1->dcmColorModel = D3DCOLOR_RGB;
340 d1->dwDevCaps = opengl_device_caps.dwDevCaps;
341 d1->dtcTransformCaps.dwSize = sizeof(D3DTRANSFORMCAPS);
342 d1->dtcTransformCaps.dwCaps = D3DTRANSFORMCAPS_CLIP;
343 d1->bClipping = TRUE;
344 d1->dlcLightingCaps.dwSize = sizeof(D3DLIGHTINGCAPS);
345 d1->dlcLightingCaps.dwCaps = D3DLIGHTCAPS_DIRECTIONAL | D3DLIGHTCAPS_PARALLELPOINT | D3DLIGHTCAPS_POINT | D3DLIGHTCAPS_SPOT;
346 d1->dlcLightingCaps.dwLightingModel = D3DLIGHTINGMODEL_RGB;
347 d1->dlcLightingCaps.dwNumLights = opengl_device_caps.dwMaxActiveLights;
348 d1->dpcLineCaps = opengl_device_caps.dpcLineCaps;
349 d1->dpcTriCaps = opengl_device_caps.dpcTriCaps;
350 d1->dwDeviceRenderBitDepth = opengl_device_caps.dwDeviceRenderBitDepth;
351 d1->dwDeviceZBufferBitDepth = opengl_device_caps.dwDeviceZBufferBitDepth;
352 d1->dwMaxBufferSize = 0;
353 d1->dwMaxVertexCount = 65536;
354 d1->dwMinTextureWidth = opengl_device_caps.dwMinTextureWidth;
355 d1->dwMinTextureHeight = opengl_device_caps.dwMinTextureHeight;
356 d1->dwMaxTextureWidth = opengl_device_caps.dwMaxTextureWidth;
357 d1->dwMaxTextureHeight = opengl_device_caps.dwMaxTextureHeight;
358 d1->dwMinStippleWidth = 1;
359 d1->dwMinStippleHeight = 1;
360 d1->dwMaxStippleWidth = 32;
361 d1->dwMaxStippleHeight = 32;
362 d1->dwMaxTextureRepeat = opengl_device_caps.dwMaxTextureRepeat;
363 d1->dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureAspectRatio;
364 d1->dwMaxAnisotropy = opengl_device_caps.dwMaxAnisotropy;
365 d1->dvGuardBandLeft = opengl_device_caps.dvGuardBandLeft;
366 d1->dvGuardBandRight = opengl_device_caps.dvGuardBandRight;
367 d1->dvGuardBandTop = opengl_device_caps.dvGuardBandTop;
368 d1->dvGuardBandBottom = opengl_device_caps.dvGuardBandBottom;
369 d1->dvExtentsAdjust = opengl_device_caps.dvExtentsAdjust;
370 d1->dwStencilCaps = opengl_device_caps.dwStencilCaps;
371 d1->dwFVFCaps = opengl_device_caps.dwFVFCaps;
372 d1->dwTextureOpCaps = opengl_device_caps.dwTextureOpCaps;
373 d1->wMaxTextureBlendStages = opengl_device_caps.wMaxTextureBlendStages;
374 d1->wMaxSimultaneousTextures = opengl_device_caps.wMaxSimultaneousTextures;
377 static void fill_opengl_caps_7(D3DDEVICEDESC7 *d)
379 *d = opengl_device_caps;
382 HRESULT d3ddevice_enumerate(LPD3DENUMDEVICESCALLBACK cb, LPVOID context, DWORD version)
384 D3DDEVICEDESC dref, d1, d2;
385 HRESULT ret_value;
387 /* Some games (Motoracer 2 demo) have the bad idea to modify the device name string.
388 Let's put the string in a sufficiently sized array in writable memory. */
389 char device_name[50];
390 strcpy(device_name,"direct3d");
392 fill_opengl_caps(&dref);
394 if (version > 1) {
395 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
396 char interface_name[] = "WINE Reference Direct3DX using OpenGL";
397 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
398 d1 = dref;
399 d2 = dref;
400 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, interface_name, device_name, &d1, &d2, context);
401 if (ret_value != D3DENUMRET_OK)
402 return ret_value;
406 char interface_name[] = "WINE Direct3DX using OpenGL";
407 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
408 d1 = dref;
409 d2 = dref;
410 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, interface_name, device_name, &d1, &d2, context);
411 if (ret_value != D3DENUMRET_OK)
412 return ret_value;
415 return D3DENUMRET_OK;
418 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
420 D3DDEVICEDESC7 ddesc;
421 char interface_name[] = "WINE Direct3D7 using OpenGL";
422 char device_name[] = "Wine D3D7 device";
424 fill_opengl_caps_7(&ddesc);
426 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
428 return cb(interface_name, device_name, &ddesc, context);
431 ULONG WINAPI
432 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
434 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
435 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
437 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
438 if (!--(This->ref)) {
439 int i;
440 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
442 /* Release texture associated with the device */
443 for (i = 0; i < MAX_TEXTURES; i++) {
444 if (This->current_texture[i] != NULL)
445 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
446 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
449 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
450 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
451 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
452 surf->aux_ctx = NULL;
453 surf->aux_data = NULL;
454 surf->aux_flip = NULL;
455 break;
458 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
459 IDirectDrawSurfaceImpl *surf2;
460 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
461 for (; surf2 != NULL; surf2 = surf2->next_attached) {
462 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
463 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
464 /* Override the Lock / Unlock function for all these surfaces */
465 surf2->lock_update = surf2->lock_update_prev;
466 surf2->unlock_update = surf2->unlock_update_prev;
467 /* And install also the blt / bltfast overrides */
468 surf2->aux_blt = NULL;
469 surf2->aux_bltfast = NULL;
471 surf2->d3ddevice = NULL;
475 /* And warn the D3D object that this device is no longer active... */
476 This->d3d->d3d_removed_device(This->d3d, This);
478 HeapFree(GetProcessHeap(), 0, This->world_mat);
479 HeapFree(GetProcessHeap(), 0, This->view_mat);
480 HeapFree(GetProcessHeap(), 0, This->proj_mat);
482 if (glThis->surface_ptr)
483 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
485 DeleteCriticalSection(&(This->crit));
487 ENTER_GL();
488 if (glThis->unlock_tex)
489 glDeleteTextures(1, &(glThis->unlock_tex));
490 glXDestroyContext(glThis->display, glThis->gl_context);
491 LEAVE_GL();
492 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
494 HeapFree(GetProcessHeap(), 0, This);
495 return 0;
497 return This->ref;
500 HRESULT WINAPI
501 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
502 LPD3DDEVICEDESC lpD3DHWDevDesc,
503 LPD3DDEVICEDESC lpD3DHELDevDesc)
505 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
506 D3DDEVICEDESC desc;
507 DWORD dwSize;
509 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
511 fill_opengl_caps(&desc);
512 dwSize = lpD3DHWDevDesc->dwSize;
513 memset(lpD3DHWDevDesc, 0, dwSize);
514 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
516 dwSize = lpD3DHELDevDesc->dwSize;
517 memset(lpD3DHELDevDesc, 0, dwSize);
518 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
520 TRACE(" returning caps : (no dump function yet)\n");
522 return DD_OK;
525 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
526 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
527 LPVOID context)
529 DDSURFACEDESC sdesc;
530 LPDDPIXELFORMAT pformat;
532 /* Do the texture enumeration */
533 sdesc.dwSize = sizeof(DDSURFACEDESC);
534 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
535 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
536 pformat = &(sdesc.ddpfPixelFormat);
537 pformat->dwSize = sizeof(DDPIXELFORMAT);
538 pformat->dwFourCC = 0;
540 TRACE("Enumerating GL_RGBA unpacked (32)\n");
541 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
542 pformat->u1.dwRGBBitCount = 32;
543 pformat->u2.dwRBitMask = 0x00FF0000;
544 pformat->u3.dwGBitMask = 0x0000FF00;
545 pformat->u4.dwBBitMask = 0x000000FF;
546 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
547 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
548 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
550 TRACE("Enumerating GL_RGB unpacked (32)\n");
551 pformat->dwFlags = DDPF_RGB;
552 pformat->u1.dwRGBBitCount = 32;
553 pformat->u2.dwRBitMask = 0x00FF0000;
554 pformat->u3.dwGBitMask = 0x0000FF00;
555 pformat->u4.dwBBitMask = 0x000000FF;
556 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
557 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
558 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
560 TRACE("Enumerating GL_RGB unpacked (24)\n");
561 pformat->dwFlags = DDPF_RGB;
562 pformat->u1.dwRGBBitCount = 24;
563 pformat->u2.dwRBitMask = 0x00FF0000;
564 pformat->u3.dwGBitMask = 0x0000FF00;
565 pformat->u4.dwBBitMask = 0x000000FF;
566 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
567 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
568 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
570 /* Note : even if this is an 'emulated' texture format, it needs to be first
571 as some dumb applications seem to rely on that. */
572 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
573 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
574 pformat->u1.dwRGBBitCount = 16;
575 pformat->u2.dwRBitMask = 0x00007C00;
576 pformat->u3.dwGBitMask = 0x000003E0;
577 pformat->u4.dwBBitMask = 0x0000001F;
578 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
579 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
580 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
582 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
583 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
584 pformat->u1.dwRGBBitCount = 16;
585 pformat->u2.dwRBitMask = 0x00000F00;
586 pformat->u3.dwGBitMask = 0x000000F0;
587 pformat->u4.dwBBitMask = 0x0000000F;
588 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
589 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
590 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
592 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
593 pformat->dwFlags = DDPF_RGB;
594 pformat->u1.dwRGBBitCount = 16;
595 pformat->u2.dwRBitMask = 0x0000F800;
596 pformat->u3.dwGBitMask = 0x000007E0;
597 pformat->u4.dwBBitMask = 0x0000001F;
598 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
599 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
600 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
602 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
603 pformat->dwFlags = DDPF_RGB;
604 pformat->u1.dwRGBBitCount = 16;
605 pformat->u2.dwRBitMask = 0x00007C00;
606 pformat->u3.dwGBitMask = 0x000003E0;
607 pformat->u4.dwBBitMask = 0x0000001F;
608 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
609 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
610 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
612 #if 0
613 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
614 find enumerated, others the last one. And both want to have the ARGB one.
616 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
618 /* See argument about the RGBA format for 'packed' texture formats */
619 TRACE("Enumerating GL_RGBA unpacked (32)\n");
620 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
621 pformat->u1.dwRGBBitCount = 32;
622 pformat->u2.dwRBitMask = 0xFF000000;
623 pformat->u3.dwGBitMask = 0x00FF0000;
624 pformat->u4.dwBBitMask = 0x0000FF00;
625 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
626 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
627 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
629 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
630 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
631 pformat->u1.dwRGBBitCount = 16;
632 pformat->u2.dwRBitMask = 0x0000F000;
633 pformat->u3.dwGBitMask = 0x00000F00;
634 pformat->u4.dwBBitMask = 0x000000F0;
635 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
636 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
637 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
639 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
640 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
641 pformat->u1.dwRGBBitCount = 16;
642 pformat->u2.dwRBitMask = 0x0000F800;
643 pformat->u3.dwGBitMask = 0x000007C0;
644 pformat->u4.dwBBitMask = 0x0000003E;
645 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
646 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
647 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
648 #endif
650 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
651 pformat->dwFlags = DDPF_RGB;
652 pformat->u1.dwRGBBitCount = 8;
653 pformat->u2.dwRBitMask = 0x000000E0;
654 pformat->u3.dwGBitMask = 0x0000001C;
655 pformat->u4.dwBBitMask = 0x00000003;
656 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
657 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
658 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
660 TRACE("Enumerating Paletted (8)\n");
661 pformat->dwFlags = DDPF_PALETTEINDEXED8;
662 pformat->u1.dwRGBBitCount = 8;
663 pformat->u2.dwRBitMask = 0x00000000;
664 pformat->u3.dwGBitMask = 0x00000000;
665 pformat->u4.dwBBitMask = 0x00000000;
666 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
667 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
668 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
670 TRACE("End of enumeration\n");
671 return DD_OK;
675 HRESULT
676 d3ddevice_find(IDirectDrawImpl *d3d,
677 LPD3DFINDDEVICESEARCH lpD3DDFS,
678 LPD3DFINDDEVICERESULT lplpD3DDevice)
680 D3DDEVICEDESC desc;
682 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
683 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
684 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
685 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
687 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
688 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
689 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
690 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
691 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
692 TRACE(" no match for this GUID.\n");
693 return DDERR_INVALIDPARAMS;
697 /* Now return our own GUID */
698 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
699 fill_opengl_caps(&desc);
700 lplpD3DDevice->ddHwDesc = desc;
701 lplpD3DDevice->ddSwDesc = desc;
703 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
705 return D3D_OK;
708 HRESULT WINAPI
709 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
710 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
711 LPVOID lpArg)
713 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
714 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
715 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
718 HRESULT WINAPI
719 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
720 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
721 LPVOID lpArg)
723 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
724 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
725 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
728 HRESULT WINAPI
729 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
730 D3DRENDERSTATETYPE dwRenderStateType,
731 DWORD dwRenderState)
733 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
734 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
736 /* Call the render state functions */
737 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
738 set_render_state(This, dwRenderStateType, &This->state_block);
740 return DD_OK;
743 HRESULT WINAPI
744 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
745 D3DRENDERSTATETYPE dwRenderStateType,
746 LPDWORD lpdwRenderState)
748 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
749 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
751 /* Call the render state functions */
752 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
754 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
756 return DD_OK;
759 HRESULT WINAPI
760 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
761 D3DLIGHTSTATETYPE dwLightStateType,
762 DWORD dwLightState)
764 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
766 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
768 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX)) {
769 TRACE("Unexpected Light State Type\n");
770 return DDERR_INVALIDPARAMS;
773 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
774 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
776 if (mat != NULL) {
777 TRACE(" activating material %p.\n", mat);
778 mat->activate(mat);
779 } else {
780 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
781 return DDERR_INVALIDPARAMS;
783 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
784 switch (dwLightState) {
785 case D3DCOLOR_MONO:
786 ERR("DDCOLOR_MONO should not happen!\n");
787 break;
788 case D3DCOLOR_RGB:
789 /* We are already in this mode */
790 TRACE("Setting color model to RGB (no-op).\n");
791 break;
792 default:
793 ERR("Unknown color model!\n");
794 return DDERR_INVALIDPARAMS;
796 } else {
797 D3DRENDERSTATETYPE rs;
798 switch (dwLightStateType) {
799 case D3DLIGHTSTATE_AMBIENT: /* 2 */
800 rs = D3DRENDERSTATE_AMBIENT;
801 break;
802 case D3DLIGHTSTATE_FOGMODE: /* 4 */
803 rs = D3DRENDERSTATE_FOGVERTEXMODE;
804 break;
805 case D3DLIGHTSTATE_FOGSTART: /* 5 */
806 rs = D3DRENDERSTATE_FOGSTART;
807 break;
808 case D3DLIGHTSTATE_FOGEND: /* 6 */
809 rs = D3DRENDERSTATE_FOGEND;
810 break;
811 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
812 rs = D3DRENDERSTATE_FOGDENSITY;
813 break;
814 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
815 rs = D3DRENDERSTATE_COLORVERTEX;
816 break;
817 default:
818 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType);
819 return DDERR_INVALIDPARAMS;
822 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
823 rs,dwLightState);
826 return DD_OK;
829 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
831 switch (d3dpt) {
832 case D3DPT_POINTLIST:
833 TRACE("Start POINTS\n");
834 glBegin(GL_POINTS);
835 break;
837 case D3DPT_LINELIST:
838 TRACE("Start LINES\n");
839 glBegin(GL_LINES);
840 break;
842 case D3DPT_LINESTRIP:
843 TRACE("Start LINE_STRIP\n");
844 glBegin(GL_LINE_STRIP);
845 break;
847 case D3DPT_TRIANGLELIST:
848 TRACE("Start TRIANGLES\n");
849 glBegin(GL_TRIANGLES);
850 break;
852 case D3DPT_TRIANGLESTRIP:
853 TRACE("Start TRIANGLE_STRIP\n");
854 glBegin(GL_TRIANGLE_STRIP);
855 break;
857 case D3DPT_TRIANGLEFAN:
858 TRACE("Start TRIANGLE_FAN\n");
859 glBegin(GL_TRIANGLE_FAN);
860 break;
862 default:
863 FIXME("Unhandled primitive %08x\n", d3dpt);
864 break;
868 /* This function calculate the Z coordinate from Zproj */
869 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
871 float a,b,c,d;
872 /* Assume that X = Y = 0 and W = 1 */
873 a = This->proj_mat->_33;
874 b = This->proj_mat->_34;
875 c = This->proj_mat->_43;
876 d = This->proj_mat->_44;
877 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
878 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
879 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
881 return (d*Zproj - c) / (a - b*Zproj);
884 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
885 int i;
887 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
889 for (i = 0; i < 3; i++) {
890 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
891 DWORD elt;
892 for (elt = 0; elt < 0x10000; elt++) {
893 /* We apply the fog transformation and cache the result */
894 DWORD fog_intensity = elt & 0xFF;
895 DWORD vertex_color = (elt >> 8) & 0xFF;
896 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
901 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
902 BOOLEAN vertex_transformed,
903 BOOLEAN vertex_lit) {
904 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
906 /* Puts GL in the correct lighting / transformation mode */
907 if ((vertex_transformed == FALSE) &&
908 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
909 /* Need to put the correct transformation again if we go from Transformed
910 vertices to non-transformed ones.
912 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
913 This->world_mat, This->view_mat, This->proj_mat);
914 glThis->transform_state = GL_TRANSFORM_NORMAL;
916 } else if ((vertex_transformed == TRUE) &&
917 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
918 /* Set our orthographic projection */
919 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
920 glThis->transform_state = GL_TRANSFORM_ORTHO;
921 d3ddevice_set_ortho(This);
925 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
926 if no fogging state change occurred */
927 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
928 if (vertex_transformed == TRUE) {
929 if (glThis->fogging != 0) {
930 glDisable(GL_FOG);
931 glThis->fogging = 0;
933 /* Now check if our fog_table still corresponds to the current vertex color.
934 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
935 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
936 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
937 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
938 /* We need to rebuild our fog table.... */
939 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
941 } else {
942 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
943 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
944 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
945 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
946 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
948 if (vertex_lit == FALSE) {
949 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
950 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
951 } else {
952 /* Special case of 'pixel fog' */
953 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
954 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
956 if (glThis->fogging == 0) {
957 glEnable(GL_FOG);
958 glThis->fogging = 1;
960 } else {
961 if (glThis->fogging != 0) {
962 glDisable(GL_FOG);
963 glThis->fogging = 0;
967 } else {
968 if (glThis->fogging != 0) {
969 glDisable(GL_FOG);
970 glThis->fogging = 0;
974 /* Handle the 'no-normal' case */
975 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
976 if (glThis->lighting == 0) {
977 glEnable(GL_LIGHTING);
978 glThis->lighting = 1;
980 } else {
981 if (glThis->lighting != 0) {
982 glDisable(GL_LIGHTING);
983 glThis->lighting = 0;
987 /* Handle the code for pre-vertex material properties */
988 if (vertex_transformed == FALSE) {
989 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
990 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
991 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
992 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
993 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
994 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
995 glEnable(GL_COLOR_MATERIAL);
1002 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
1003 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
1005 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1007 switch (d3dvt) {
1008 case D3DVT_VERTEX: {
1009 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1010 strided.position.dwStride = sizeof(D3DVERTEX);
1011 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1012 strided.normal.dwStride = sizeof(D3DVERTEX);
1013 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1014 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
1015 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1016 } break;
1018 case D3DVT_LVERTEX: {
1019 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1020 strided.position.dwStride = sizeof(D3DLVERTEX);
1021 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1022 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1023 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1024 strided.specular.dwStride = sizeof(D3DLVERTEX);
1025 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1026 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
1027 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1028 } break;
1030 case D3DVT_TLVERTEX: {
1031 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1032 strided.position.dwStride = sizeof(D3DTLVERTEX);
1033 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1034 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1035 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1036 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1037 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1038 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1039 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1040 } break;
1042 default:
1043 FIXME("Unhandled vertex type %08x\n", d3dvt);
1044 break;
1048 HRESULT WINAPI
1049 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1050 D3DPRIMITIVETYPE d3dptPrimitiveType,
1051 D3DVERTEXTYPE d3dvtVertexType,
1052 LPVOID lpvVertices,
1053 DWORD dwVertexCount,
1054 DWORD dwFlags)
1056 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1058 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1059 if (TRACE_ON(ddraw)) {
1060 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1063 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1065 return DD_OK;
1068 HRESULT WINAPI
1069 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1070 D3DPRIMITIVETYPE d3dptPrimitiveType,
1071 D3DVERTEXTYPE d3dvtVertexType,
1072 LPVOID lpvVertices,
1073 DWORD dwVertexCount,
1074 LPWORD dwIndices,
1075 DWORD dwIndexCount,
1076 DWORD dwFlags)
1078 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1079 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1080 if (TRACE_ON(ddraw)) {
1081 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1084 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1086 return DD_OK;
1089 HRESULT WINAPI
1090 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1091 LPD3DEXECUTEBUFFERDESC lpDesc,
1092 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1093 IUnknown* pUnkOuter)
1095 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1096 IDirect3DExecuteBufferImpl *ret;
1097 HRESULT ret_value;
1099 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1101 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1102 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1104 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1106 return ret_value;
1109 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
1110 static BOOLEAN first = TRUE;
1111 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
1112 int row;
1113 GLenum type;
1115 if (first == TRUE) {
1116 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1117 first = FALSE;
1120 TRACE("flushing ZBuffer back to GL\n");
1122 if (gl_d3d_dev->transform_state != GL_TRANSFORM_ORTHO) {
1123 gl_d3d_dev->transform_state = GL_TRANSFORM_ORTHO;
1124 d3ddevice_set_ortho(d3d_dev);
1127 glMatrixMode(GL_MODELVIEW);
1128 glLoadIdentity();
1130 if (gl_d3d_dev->depth_test == 0) glEnable(GL_DEPTH_TEST);
1131 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS) glDepthFunc(GL_ALWAYS);
1132 glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1134 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1135 in some drivers...
1137 switch (surf->surface_desc.u4.ddpfPixelFormat.u1.dwZBufferBitDepth) {
1138 case 16: type = GL_UNSIGNED_SHORT; break;
1139 case 32: type = GL_UNSIGNED_INT; break;
1140 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state;
1143 for (row = 0; row < surf->surface_desc.dwHeight; row++) {
1144 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1145 glRasterPos2i(0, row + 1);
1146 glDrawPixels(surf->surface_desc.dwWidth, 1, GL_DEPTH_COMPONENT, type,
1147 ((unsigned char *) surf->surface_desc.lpSurface) + (row * surf->surface_desc.u1.lPitch));
1150 restore_state:
1151 glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1152 if (d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1] != D3DCMP_ALWAYS)
1153 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev->state_block.render_state[D3DRENDERSTATE_ZFUNC - 1]));
1154 if (gl_d3d_dev->depth_test == 0) glDisable(GL_DEPTH_TEST);
1157 /* These are the various handler used in the generic path */
1158 inline static void handle_xyz(D3DVALUE *coords) {
1159 glVertex3fv(coords);
1161 inline static void handle_xyzrhw(D3DVALUE *coords) {
1162 if (coords[3] < 1e-8)
1163 glVertex3fv(coords);
1164 else {
1165 GLfloat w = 1.0 / coords[3];
1167 glVertex4f(coords[0] * w,
1168 coords[1] * w,
1169 coords[2] * w,
1173 inline static void handle_normal(D3DVALUE *coords) {
1174 glNormal3fv(coords);
1177 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1178 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1179 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1180 glColor4ub((*color >> 16) & 0xFF,
1181 (*color >> 8) & 0xFF,
1182 (*color >> 0) & 0xFF,
1183 (*color >> 24) & 0xFF);
1184 } else {
1185 glColor3ub((*color >> 16) & 0xFF,
1186 (*color >> 8) & 0xFF,
1187 (*color >> 0) & 0xFF);
1191 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1192 glColor4ub((*color >> 16) & 0xFF,
1193 (*color >> 8) & 0xFF,
1194 (*color >> 0) & 0xFF,
1195 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1198 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1199 if ((lighted == FALSE) &&
1200 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1201 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1202 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1203 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1204 handle_diffuse_base(sb, color);
1206 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1207 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1208 handle_diffuse_base(sb, color);
1210 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1211 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1212 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1213 handle_diffuse_base(sb, color);
1215 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1216 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1217 handle_diffuse_base(sb, color);
1219 } else {
1220 handle_diffuse_base(sb, color);
1224 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1225 if ((lighted == FALSE) &&
1226 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1227 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1228 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1229 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1230 handle_specular_base(sb, color);
1232 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1233 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1234 handle_specular_base(sb, color);
1236 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1237 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1238 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1239 handle_specular_base(sb, color);
1241 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1242 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1243 handle_specular_base(sb, color);
1246 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1249 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1250 if (lighted == TRUE) {
1251 DWORD color = *color_d;
1252 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1253 /* Special case where the specular value is used to do fogging */
1254 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1255 color &= 0xFF000000; /* Only keep the alpha component */
1256 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1257 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1258 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1260 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1261 /* Standard specular value in transformed mode. TODO */
1263 handle_diffuse_base(sb, &color);
1264 } else {
1265 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1266 handle_diffuse(sb, color_d, FALSE);
1267 handle_specular(sb, color_s, FALSE);
1268 } else {
1269 /* In that case, only put the diffuse color... */
1270 handle_diffuse_base(sb, color_d);
1275 inline static void handle_texture(D3DVALUE *coords) {
1276 glTexCoord2fv(coords);
1278 inline static void handle_textures(D3DVALUE *coords, int tex_stage) {
1279 if (GL_extensions.glMultiTexCoord2fv) {
1280 GL_extensions.glMultiTexCoord2fv(GL_TEXTURE0_WINE + tex_stage, coords);
1281 } else {
1282 if (tex_stage == 0) glTexCoord2fv(coords);
1286 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1287 D3DPRIMITIVETYPE d3dptPrimitiveType,
1288 DWORD d3dvtVertexType,
1289 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1290 DWORD dwVertexCount,
1291 LPWORD dwIndices,
1292 DWORD dwIndexCount,
1293 DWORD dwFlags)
1295 BOOLEAN vertex_lighted = FALSE;
1296 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1297 int num_active_stages = 0;
1299 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1300 if (TRACE_ON(ddraw)) {
1301 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1304 /* This is to prevent 'thread contention' between a thread locking the device and another
1305 doing 3D display on it... */
1306 EnterCriticalSection(&(This->crit));
1308 ENTER_GL();
1309 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1310 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1312 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1314 if (This->current_zbuffer == NULL) {
1315 /* Search for an attached ZBuffer */
1316 static const DDSCAPS2 zbuf_caps = { DDSCAPS_ZBUFFER, 0, 0, 0 };
1317 LPDIRECTDRAWSURFACE7 zbuf;
1318 HRESULT hr;
1320 hr = IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This->surface, IDirectDrawSurface7),
1321 (DDSCAPS2 *) &zbuf_caps, &zbuf);
1322 if (!FAILED(hr)) {
1323 This->current_zbuffer = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, zbuf);
1324 IDirectDrawSurface7_Release(zbuf);
1327 if (This->current_zbuffer != NULL) {
1328 if (This->current_zbuffer->get_dirty_status(This->current_zbuffer, NULL)) {
1329 flush_zbuffer_to_GL(This, NULL, This->current_zbuffer);
1333 if ( ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) ||
1334 ((d3dvtVertexType & D3DFVF_NORMAL) == 0) )
1335 vertex_lighted = TRUE;
1337 /* Compute the number of active texture stages and set the various texture parameters */
1338 num_active_stages = draw_primitive_handle_textures(This);
1340 /* And restore to handle '0' in the case we use glTexCorrd calls */
1341 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1342 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1343 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1346 draw_primitive_handle_GL_state(This,
1347 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1348 vertex_lighted);
1349 draw_primitive_start_GL(d3dptPrimitiveType);
1351 /* Some fast paths first before the generic case.... */
1352 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1353 int index;
1355 for (index = 0; index < dwIndexCount; index++) {
1356 int i = (dwIndices == NULL) ? index : dwIndices[index];
1357 D3DVALUE *normal =
1358 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1359 D3DVALUE *tex_coord =
1360 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1361 D3DVALUE *position =
1362 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1364 handle_normal(normal);
1365 handle_texture(tex_coord);
1366 handle_xyz(position);
1368 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1369 position[0], position[1], position[2],
1370 normal[0], normal[1], normal[2],
1371 tex_coord[0], tex_coord[1]);
1373 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1374 int index;
1376 for (index = 0; index < dwIndexCount; index++) {
1377 int i = (dwIndices == NULL) ? index : dwIndices[index];
1378 DWORD *color_d =
1379 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1380 DWORD *color_s =
1381 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1382 D3DVALUE *tex_coord =
1383 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1384 D3DVALUE *position =
1385 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1387 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1388 handle_texture(tex_coord);
1389 handle_xyzrhw(position);
1391 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1392 position[0], position[1], position[2], position[3],
1393 (*color_d >> 16) & 0xFF,
1394 (*color_d >> 8) & 0xFF,
1395 (*color_d >> 0) & 0xFF,
1396 (*color_d >> 24) & 0xFF,
1397 (*color_s >> 16) & 0xFF,
1398 (*color_s >> 8) & 0xFF,
1399 (*color_s >> 0) & 0xFF,
1400 (*color_s >> 24) & 0xFF,
1401 tex_coord[0], tex_coord[1]);
1403 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1404 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1405 /* This is the 'slow path' but that should support all possible vertex formats out there...
1406 Note that people should write a fast path for all vertex formats out there...
1408 int index;
1409 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1410 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1412 for (index = 0; index < dwIndexCount; index++) {
1413 int i = (dwIndices == NULL) ? index : dwIndices[index];
1414 int tex_stage;
1416 if (d3dvtVertexType & D3DFVF_NORMAL) {
1417 D3DVALUE *normal =
1418 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1419 handle_normal(normal);
1421 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1422 DWORD *color_d =
1423 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1424 DWORD *color_s =
1425 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1426 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1427 } else {
1428 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1429 DWORD *color_s =
1430 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1431 handle_specular(&(This->state_block), color_s, vertex_lighted);
1432 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1433 DWORD *color_d =
1434 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1435 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1439 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1440 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1441 if (tex_index >= num_tex_index) {
1442 handle_textures((D3DVALUE *) no_index, tex_stage);
1443 } else {
1444 D3DVALUE *tex_coord =
1445 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1446 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1447 handle_textures(tex_coord, tex_stage);
1451 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1452 D3DVALUE *position =
1453 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1454 handle_xyz(position);
1455 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1456 D3DVALUE *position =
1457 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1458 handle_xyzrhw(position);
1461 if (TRACE_ON(ddraw_geom)) {
1462 int tex_index;
1464 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1465 D3DVALUE *position =
1466 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1467 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1468 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1469 D3DVALUE *position =
1470 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1471 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1473 if (d3dvtVertexType & D3DFVF_NORMAL) {
1474 D3DVALUE *normal =
1475 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1476 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1478 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1479 DWORD *color_d =
1480 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1481 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1482 (*color_d >> 16) & 0xFF,
1483 (*color_d >> 8) & 0xFF,
1484 (*color_d >> 0) & 0xFF,
1485 (*color_d >> 24) & 0xFF);
1487 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1488 DWORD *color_s =
1489 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1490 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1491 (*color_s >> 16) & 0xFF,
1492 (*color_s >> 8) & 0xFF,
1493 (*color_s >> 0) & 0xFF,
1494 (*color_s >> 24) & 0xFF);
1496 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1497 D3DVALUE *tex_coord =
1498 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1499 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1500 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1502 TRACE_(ddraw_geom)("\n");
1505 } else {
1506 ERR(" matrix weighting not handled yet....\n");
1509 glEnd();
1511 /* Whatever the case, disable the color material stuff */
1512 glDisable(GL_COLOR_MATERIAL);
1514 LEAVE_GL();
1515 TRACE("End\n");
1517 LeaveCriticalSection(&(This->crit));
1520 HRESULT WINAPI
1521 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1522 D3DPRIMITIVETYPE d3dptPrimitiveType,
1523 DWORD d3dvtVertexType,
1524 LPVOID lpvVertices,
1525 DWORD dwVertexCount,
1526 DWORD dwFlags)
1528 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1529 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1531 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1532 if (TRACE_ON(ddraw)) {
1533 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1536 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1537 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1539 return DD_OK;
1542 HRESULT WINAPI
1543 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1544 D3DPRIMITIVETYPE d3dptPrimitiveType,
1545 DWORD d3dvtVertexType,
1546 LPVOID lpvVertices,
1547 DWORD dwVertexCount,
1548 LPWORD dwIndices,
1549 DWORD dwIndexCount,
1550 DWORD dwFlags)
1552 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1553 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1555 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1556 if (TRACE_ON(ddraw)) {
1557 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1560 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1561 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1563 return DD_OK;
1566 HRESULT WINAPI
1567 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1568 D3DPRIMITIVETYPE d3dptPrimitiveType,
1569 DWORD dwVertexType,
1570 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1571 DWORD dwVertexCount,
1572 DWORD dwFlags)
1574 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1576 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1577 if (TRACE_ON(ddraw)) {
1578 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1580 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1582 return DD_OK;
1585 HRESULT WINAPI
1586 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1587 D3DPRIMITIVETYPE d3dptPrimitiveType,
1588 DWORD dwVertexType,
1589 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1590 DWORD dwVertexCount,
1591 LPWORD lpIndex,
1592 DWORD dwIndexCount,
1593 DWORD dwFlags)
1595 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1597 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1598 if (TRACE_ON(ddraw)) {
1599 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1602 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1604 return DD_OK;
1607 HRESULT WINAPI
1608 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1609 D3DPRIMITIVETYPE d3dptPrimitiveType,
1610 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1611 DWORD dwStartVertex,
1612 DWORD dwNumVertices,
1613 DWORD dwFlags)
1615 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1616 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1617 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1619 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1620 if (TRACE_ON(ddraw)) {
1621 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1624 if (vb_impl->processed == TRUE) {
1625 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1626 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1628 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1629 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1630 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1632 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1633 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1635 } else {
1636 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1637 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1640 return DD_OK;
1643 HRESULT WINAPI
1644 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1645 D3DPRIMITIVETYPE d3dptPrimitiveType,
1646 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1647 DWORD dwStartVertex,
1648 DWORD dwNumVertices,
1649 LPWORD lpwIndices,
1650 DWORD dwIndexCount,
1651 DWORD dwFlags)
1653 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1654 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1655 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1657 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1658 if (TRACE_ON(ddraw)) {
1659 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1662 if (vb_impl->processed == TRUE) {
1663 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1664 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1666 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1667 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1668 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1670 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1671 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1673 } else {
1674 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1675 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1678 return DD_OK;
1681 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1682 static BOOLEAN
1683 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1685 BOOLEAN is_complement = FALSE;
1686 BOOLEAN is_alpha_replicate = FALSE;
1687 BOOLEAN handled = TRUE;
1688 GLenum src;
1689 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1690 int num;
1692 if (is_color) {
1693 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1694 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1695 else {
1696 handled = FALSE;
1697 num = 0;
1699 if (tex_op == D3DTOP_SELECTARG2) {
1700 num = 1 - num;
1702 } else {
1703 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1704 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1705 else {
1706 handled = FALSE;
1707 num = 0;
1709 if (tex_op == D3DTOP_SELECTARG2) {
1710 num = 1 - num;
1714 if (dwState & D3DTA_COMPLEMENT) {
1715 is_complement = TRUE;
1717 if (dwState & D3DTA_ALPHAREPLICATE) {
1718 is_alpha_replicate = TRUE;
1720 dwState &= D3DTA_SELECTMASK;
1721 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1722 dwState = D3DTA_DIFFUSE;
1725 switch (dwState) {
1726 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1727 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1728 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1729 case D3DTA_TFACTOR: {
1730 /* Get the constant value from the current rendering state */
1731 GLfloat color[4];
1732 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1734 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1735 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1736 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1737 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1738 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1740 src = GL_CONSTANT_EXT;
1741 } break;
1742 default: src = GL_TEXTURE; handled = FALSE; break;
1745 if (is_color) {
1746 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1747 if (is_alpha_replicate) {
1748 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1749 } else {
1750 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1752 } else {
1753 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1754 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1757 return handled;
1760 HRESULT WINAPI
1761 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1762 DWORD dwStage,
1763 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1764 DWORD dwState)
1766 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1767 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1768 const char *type;
1769 DWORD prev_state;
1770 GLenum unit;
1772 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1774 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1775 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1776 return DD_OK;
1779 unit = GL_TEXTURE0_WINE + dwStage;
1780 if (unit != glThis->current_active_tex_unit) {
1781 GL_extensions.glActiveTexture(unit);
1782 glThis->current_active_tex_unit = unit;
1785 switch (d3dTexStageStateType) {
1786 #define GEN_CASE(a) case a: type = #a; break
1787 GEN_CASE(D3DTSS_COLOROP);
1788 GEN_CASE(D3DTSS_COLORARG1);
1789 GEN_CASE(D3DTSS_COLORARG2);
1790 GEN_CASE(D3DTSS_ALPHAOP);
1791 GEN_CASE(D3DTSS_ALPHAARG1);
1792 GEN_CASE(D3DTSS_ALPHAARG2);
1793 GEN_CASE(D3DTSS_BUMPENVMAT00);
1794 GEN_CASE(D3DTSS_BUMPENVMAT01);
1795 GEN_CASE(D3DTSS_BUMPENVMAT10);
1796 GEN_CASE(D3DTSS_BUMPENVMAT11);
1797 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1798 GEN_CASE(D3DTSS_ADDRESS);
1799 GEN_CASE(D3DTSS_ADDRESSU);
1800 GEN_CASE(D3DTSS_ADDRESSV);
1801 GEN_CASE(D3DTSS_BORDERCOLOR);
1802 GEN_CASE(D3DTSS_MAGFILTER);
1803 GEN_CASE(D3DTSS_MINFILTER);
1804 GEN_CASE(D3DTSS_MIPFILTER);
1805 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1806 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1807 GEN_CASE(D3DTSS_MAXANISOTROPY);
1808 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1809 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1810 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1811 #undef GEN_CASE
1812 default: type = "UNKNOWN";
1815 /* Store the values in the state array */
1816 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1817 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1818 /* Some special cases when one state modifies more than one... */
1819 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1820 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1821 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1824 ENTER_GL();
1826 switch (d3dTexStageStateType) {
1827 case D3DTSS_MINFILTER:
1828 case D3DTSS_MIPFILTER:
1829 if (TRACE_ON(ddraw)) {
1830 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1831 switch ((D3DTEXTUREMINFILTER) dwState) {
1832 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1833 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1834 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1836 } else {
1837 switch ((D3DTEXTUREMIPFILTER) dwState) {
1838 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1839 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1840 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1841 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1845 break;
1847 case D3DTSS_MAGFILTER:
1848 if (TRACE_ON(ddraw)) {
1849 switch ((D3DTEXTUREMAGFILTER) dwState) {
1850 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1851 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1852 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1855 break;
1857 case D3DTSS_ADDRESS:
1858 case D3DTSS_ADDRESSU:
1859 case D3DTSS_ADDRESSV: {
1860 switch ((D3DTEXTUREADDRESS) dwState) {
1861 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1862 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1863 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1864 case D3DTADDRESS_MIRROR:
1865 if (GL_extensions.mirrored_repeat == TRUE) {
1866 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1867 } else {
1868 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1870 break;
1871 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1873 } break;
1875 case D3DTSS_ALPHAOP:
1876 case D3DTSS_COLOROP: {
1877 int scale = 1;
1878 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1879 const char *value;
1880 int handled = 1;
1882 switch (dwState) {
1883 #define GEN_CASE(a) case a: value = #a; break
1884 GEN_CASE(D3DTOP_DISABLE);
1885 GEN_CASE(D3DTOP_SELECTARG1);
1886 GEN_CASE(D3DTOP_SELECTARG2);
1887 GEN_CASE(D3DTOP_MODULATE);
1888 GEN_CASE(D3DTOP_MODULATE2X);
1889 GEN_CASE(D3DTOP_MODULATE4X);
1890 GEN_CASE(D3DTOP_ADD);
1891 GEN_CASE(D3DTOP_ADDSIGNED);
1892 GEN_CASE(D3DTOP_ADDSIGNED2X);
1893 GEN_CASE(D3DTOP_SUBTRACT);
1894 GEN_CASE(D3DTOP_ADDSMOOTH);
1895 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1896 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1897 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1898 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1899 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1900 GEN_CASE(D3DTOP_PREMODULATE);
1901 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1902 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1903 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1904 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1905 GEN_CASE(D3DTOP_BUMPENVMAP);
1906 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1907 GEN_CASE(D3DTOP_DOTPRODUCT3);
1908 GEN_CASE(D3DTOP_FORCE_DWORD);
1909 #undef GEN_CASE
1910 default: value = "UNKNOWN";
1913 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
1914 glDisable(GL_TEXTURE_2D);
1915 TRACE(" disabling 2D texturing.\n");
1916 } else {
1917 /* Re-enable texturing */
1918 if (This->current_texture[0] != NULL) {
1919 glEnable(GL_TEXTURE_2D);
1920 TRACE(" enabling 2D texturing.\n");
1923 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1924 if (dwState != D3DTOP_DISABLE) {
1925 if (glThis->current_tex_env != GL_COMBINE_EXT) {
1926 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1927 glThis->current_tex_env = GL_COMBINE_EXT;
1931 /* Now set up the operand correctly */
1932 switch (dwState) {
1933 case D3DTOP_DISABLE:
1934 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1935 and it works, so ignore this op */
1936 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1937 break;
1939 case D3DTOP_SELECTARG1:
1940 case D3DTOP_SELECTARG2:
1941 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1942 break;
1944 case D3DTOP_MODULATE4X:
1945 scale = scale * 2; /* Drop through */
1946 case D3DTOP_MODULATE2X:
1947 scale = scale * 2; /* Drop through */
1948 case D3DTOP_MODULATE:
1949 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1950 break;
1952 case D3DTOP_ADD:
1953 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1954 break;
1956 case D3DTOP_ADDSIGNED2X:
1957 scale = scale * 2; /* Drop through */
1958 case D3DTOP_ADDSIGNED:
1959 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1960 break;
1962 /* For the four blending modes, use the Arg2 parameter */
1963 case D3DTOP_BLENDDIFFUSEALPHA:
1964 case D3DTOP_BLENDTEXTUREALPHA:
1965 case D3DTOP_BLENDFACTORALPHA:
1966 case D3DTOP_BLENDCURRENTALPHA: {
1967 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1969 switch (dwState) {
1970 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1971 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1972 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1973 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1976 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1977 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1978 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1979 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1980 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1981 } break;
1983 default:
1984 handled = FALSE;
1985 break;
1989 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1990 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1991 /* Switch the arguments if needed... */
1992 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1993 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1994 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1995 dwState);
1996 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1997 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1998 dwState);
1999 } else {
2000 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
2001 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
2002 dwState);
2003 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
2004 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
2005 dwState);
2009 if (handled) {
2010 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
2011 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
2012 } else {
2013 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
2015 TRACE(" Stage type is : %s => %s\n", type, value);
2016 } else {
2017 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
2019 } break;
2021 case D3DTSS_COLORARG1:
2022 case D3DTSS_COLORARG2:
2023 case D3DTSS_ALPHAARG1:
2024 case D3DTSS_ALPHAARG2: {
2025 const char *value, *value_comp = "", *value_alpha = "";
2026 BOOLEAN handled;
2027 D3DTEXTUREOP tex_op;
2029 switch (dwState & D3DTA_SELECTMASK) {
2030 #define GEN_CASE(a) case a: value = #a; break
2031 GEN_CASE(D3DTA_DIFFUSE);
2032 GEN_CASE(D3DTA_CURRENT);
2033 GEN_CASE(D3DTA_TEXTURE);
2034 GEN_CASE(D3DTA_TFACTOR);
2035 GEN_CASE(D3DTA_SPECULAR);
2036 #undef GEN_CASE
2037 default: value = "UNKNOWN";
2039 if (dwState & D3DTA_COMPLEMENT) {
2040 value_comp = " | D3DTA_COMPLEMENT";
2042 if (dwState & D3DTA_ALPHAREPLICATE) {
2043 value_alpha = " | D3DTA_ALPHAREPLICATE";
2046 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
2047 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
2048 } else {
2049 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
2052 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
2054 if (handled) {
2055 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2056 } else {
2057 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
2059 } break;
2061 case D3DTSS_MIPMAPLODBIAS: {
2062 D3DVALUE value = *((D3DVALUE *) &dwState);
2063 BOOLEAN handled = TRUE;
2065 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
2066 handled = FALSE;
2068 if (handled) {
2069 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2070 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2071 } else {
2072 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2074 } break;
2076 case D3DTSS_MAXMIPLEVEL:
2077 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2078 break;
2080 case D3DTSS_BORDERCOLOR:
2081 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2082 ((dwState >> 16) & 0xFF),
2083 ((dwState >> 8) & 0xFF),
2084 ((dwState >> 0) & 0xFF),
2085 ((dwState >> 24) & 0xFF));
2086 break;
2088 case D3DTSS_TEXCOORDINDEX: {
2089 BOOLEAN handled = TRUE;
2090 const char *value;
2092 switch (dwState & 0xFFFF0000) {
2093 #define GEN_CASE(a) case a: value = #a; break
2094 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2095 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2096 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2097 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2098 #undef GEN_CASE
2099 default: value = "UNKNOWN";
2101 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2102 handled = FALSE;
2104 if (handled) {
2105 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2106 } else {
2107 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2109 } break;
2111 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2112 const char *projected = "", *value;
2113 BOOLEAN handled = TRUE;
2114 switch (dwState & 0xFF) {
2115 #define GEN_CASE(a) case a: value = #a; break
2116 GEN_CASE(D3DTTFF_DISABLE);
2117 GEN_CASE(D3DTTFF_COUNT1);
2118 GEN_CASE(D3DTTFF_COUNT2);
2119 GEN_CASE(D3DTTFF_COUNT3);
2120 GEN_CASE(D3DTTFF_COUNT4);
2121 #undef GEN_CASE
2122 default: value = "UNKNOWN";
2124 if (dwState & D3DTTFF_PROJECTED) {
2125 projected = " | D3DTTFF_PROJECTED";
2126 handled = FALSE;
2129 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2130 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2133 if (handled == TRUE) {
2134 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2135 } else {
2136 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2138 } break;
2140 default:
2141 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2142 break;
2145 LEAVE_GL();
2147 return DD_OK;
2150 static DWORD
2151 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2153 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2154 DWORD stage;
2156 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2157 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2158 GLenum unit;
2160 /* First check if we need to bind any other texture for this stage */
2161 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2162 if (This->current_texture[stage] == NULL) {
2163 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2165 unit = GL_TEXTURE0_WINE + stage;
2166 if (unit != glThis->current_active_tex_unit) {
2167 GL_extensions.glActiveTexture(unit);
2168 glThis->current_active_tex_unit = unit;
2170 glBindTexture(GL_TEXTURE_2D, 0);
2172 if (stage == 0) {
2173 glDisable(GL_TEXTURE_2D);
2175 } else {
2176 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
2178 unit = GL_TEXTURE0_WINE + stage;
2179 if (unit != glThis->current_active_tex_unit) {
2180 GL_extensions.glActiveTexture(unit);
2181 glThis->current_active_tex_unit = unit;
2184 if (glThis->current_bound_texture[stage] == NULL) {
2185 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2186 TRACE(" enabling 2D texturing and");
2187 glEnable(GL_TEXTURE_2D);
2190 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2191 glBindTexture(GL_TEXTURE_2D, tex_name);
2194 glThis->current_bound_texture[stage] = This->current_texture[stage];
2195 } else {
2196 if (glThis->current_bound_texture[stage] == NULL) {
2197 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2198 } else {
2199 TRACE(" using already bound texture id %d for stage %ld.\n",
2200 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2204 /* If no texure valid for this stage, go out of the loop */
2205 if (This->current_texture[stage] == NULL) break;
2207 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2208 This will also update the various texture parameters if needed.
2210 gltex_upload_texture(surf_ptr, This, stage);
2213 return stage;
2216 HRESULT WINAPI
2217 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2218 DWORD dwStage,
2219 LPDIRECTDRAWSURFACE7 lpTexture2)
2221 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2223 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2225 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2226 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2227 if (lpTexture2 != NULL) {
2228 WARN(" setting a texture to a non-supported texture stage !\n");
2230 return DD_OK;
2233 if (This->current_texture[dwStage] != NULL) {
2234 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2237 if (lpTexture2 == NULL) {
2238 This->current_texture[dwStage] = NULL;
2239 } else {
2240 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2241 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2242 This->current_texture[dwStage] = tex_impl;
2245 return DD_OK;
2248 HRESULT WINAPI
2249 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2250 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2252 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2253 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2255 fill_opengl_caps_7(lpD3DHELDevDesc);
2257 TRACE(" returning caps : no dump function yet.\n");
2259 return DD_OK;
2262 HRESULT WINAPI
2263 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2264 LPD3DMATERIAL7 lpMat)
2266 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2267 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2269 if (TRACE_ON(ddraw)) {
2270 TRACE(" material is : \n");
2271 dump_D3DMATERIAL7(lpMat);
2274 This->current_material = *lpMat;
2276 ENTER_GL();
2277 glMaterialfv(GL_FRONT_AND_BACK,
2278 GL_DIFFUSE,
2279 (float *) &(This->current_material.u.diffuse));
2280 glMaterialfv(GL_FRONT_AND_BACK,
2281 GL_AMBIENT,
2282 (float *) &(This->current_material.u1.ambient));
2283 glMaterialfv(GL_FRONT_AND_BACK,
2284 GL_SPECULAR,
2285 (float *) &(This->current_material.u2.specular));
2286 glMaterialfv(GL_FRONT_AND_BACK,
2287 GL_EMISSION,
2288 (float *) &(This->current_material.u3.emissive));
2289 glMaterialf(GL_FRONT_AND_BACK,
2290 GL_SHININESS,
2291 This->current_material.u4.power); /* Not sure about this... */
2292 LEAVE_GL();
2294 return DD_OK;
2298 HRESULT WINAPI
2299 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2300 DWORD dwLightIndex,
2301 LPD3DLIGHT7 lpLight)
2303 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2304 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2305 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2307 if (TRACE_ON(ddraw)) {
2308 TRACE(" setting light : \n");
2309 dump_D3DLIGHT7(lpLight);
2312 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2313 This->set_lights |= 0x00000001 << dwLightIndex;
2314 This->light_parameters[dwLightIndex] = *lpLight;
2316 /* Some checks to print out nice warnings :-) */
2317 switch (lpLight->dltType) {
2318 case D3DLIGHT_DIRECTIONAL:
2319 case D3DLIGHT_POINT:
2320 /* These are handled properly... */
2321 break;
2323 case D3DLIGHT_SPOT:
2324 if ((lpLight->dvTheta != 0.0) ||
2325 (lpLight->dvTheta != lpLight->dvPhi)) {
2326 ERR("dvTheta not fully supported yet !\n");
2328 break;
2330 default:
2331 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2334 /* This will force the Light setting on next drawing of primitives */
2335 glThis->transform_state = GL_TRANSFORM_NONE;
2337 return DD_OK;
2340 HRESULT WINAPI
2341 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2342 DWORD dwLightIndex,
2343 BOOL bEnable)
2345 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2346 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2348 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2350 ENTER_GL();
2351 if (bEnable) {
2352 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2353 /* Set the default parameters.. */
2354 TRACE(" setting default light parameters...\n");
2355 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2357 glEnable(GL_LIGHT0 + dwLightIndex);
2358 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2359 /* This light gets active... Need to update its parameters to GL before the next drawing */
2360 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2362 This->active_lights |= 0x00000001 << dwLightIndex;
2363 glThis->transform_state = GL_TRANSFORM_NONE;
2365 } else {
2366 glDisable(GL_LIGHT0 + dwLightIndex);
2367 This->active_lights &= ~(0x00000001 << dwLightIndex);
2369 LEAVE_GL();
2371 return DD_OK;
2374 HRESULT WINAPI
2375 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2377 ICOM_THIS(IDirect3DDeviceImpl,iface);
2378 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2380 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2382 if (dwIndex >= This->max_clipping_planes) {
2383 return DDERR_INVALIDPARAMS;
2386 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2388 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2390 /* This is to force the reset of the transformation matrices on the next drawing.
2391 * This is needed to use the correct matrices for the various clipping planes.
2393 glThis->transform_state = GL_TRANSFORM_NONE;
2395 return D3D_OK;
2398 HRESULT WINAPI
2399 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2400 LPD3DVIEWPORT7 lpData)
2402 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2403 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2405 if (TRACE_ON(ddraw)) {
2406 TRACE(" viewport is : \n");
2407 TRACE(" - dwX = %ld dwY = %ld\n",
2408 lpData->dwX, lpData->dwY);
2409 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2410 lpData->dwWidth, lpData->dwHeight);
2411 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2412 lpData->dvMinZ, lpData->dvMaxZ);
2414 ENTER_GL();
2416 /* Set the viewport */
2417 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2418 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2419 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2421 if ((lpData->dwX != This->active_viewport.dwX) ||
2422 (lpData->dwY != This->active_viewport.dwY) ||
2423 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2424 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2425 glViewport(lpData->dwX,
2426 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2427 lpData->dwWidth, lpData->dwHeight);
2430 LEAVE_GL();
2432 This->active_viewport = *lpData;
2434 return DD_OK;
2437 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2438 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2439 #else
2440 # define XCAST(fun) (void*)
2441 #endif
2443 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2445 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2446 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2447 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2448 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2449 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2450 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2451 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2452 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2453 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2454 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2455 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2456 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2457 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2458 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2459 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2460 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2461 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2462 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2463 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2464 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2465 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2466 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2467 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2468 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2469 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2470 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2471 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2472 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2473 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2474 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2475 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2476 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2477 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2478 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2479 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2480 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2481 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2482 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2483 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2484 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2485 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2486 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2487 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2488 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2489 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2490 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2491 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2492 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2493 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2494 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2497 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2498 #undef XCAST
2499 #endif
2502 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2503 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2504 #else
2505 # define XCAST(fun) (void*)
2506 #endif
2508 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2510 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2511 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2512 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2513 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2514 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2515 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2516 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2517 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2518 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2519 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2520 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2521 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2522 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2523 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2524 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2525 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2526 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2527 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2528 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2529 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2530 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2531 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2532 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2533 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2534 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2535 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2536 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2537 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2538 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2539 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2540 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2541 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2542 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2543 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2544 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2545 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2546 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2547 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2548 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2549 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2550 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2551 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2552 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2555 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2556 #undef XCAST
2557 #endif
2560 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2561 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2562 #else
2563 # define XCAST(fun) (void*)
2564 #endif
2566 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2568 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2569 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2570 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2571 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2572 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2573 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2574 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2575 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2576 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2577 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2578 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2579 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2580 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2581 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2582 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2583 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2584 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2585 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2586 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2587 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2588 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2589 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2590 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2591 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2592 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2593 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2594 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2595 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2596 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2597 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2598 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2599 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2600 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2601 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2604 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2605 #undef XCAST
2606 #endif
2609 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2610 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2611 #else
2612 # define XCAST(fun) (void*)
2613 #endif
2615 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2617 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2618 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2619 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2620 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2621 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2622 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2623 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2624 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2625 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2626 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2627 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2628 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2629 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2630 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2631 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2632 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2633 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2634 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2635 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2636 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2637 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2638 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2639 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2642 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2643 #undef XCAST
2644 #endif
2646 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2647 WINE_GL_BUFFER_TYPE buffer_type,
2648 DWORD dwCount,
2649 LPD3DRECT lpRects,
2650 DWORD dwFlags,
2651 DWORD dwColor,
2652 D3DVALUE dvZ,
2653 DWORD dwStencil)
2655 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2656 GLbitfield bitfield = 0;
2657 D3DRECT rect;
2658 int i;
2660 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2661 if (TRACE_ON(ddraw)) {
2662 if (dwCount > 0) {
2663 int i;
2664 TRACE(" rectangles : \n");
2665 for (i = 0; i < dwCount; i++) {
2666 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2671 if (dwCount == 0) {
2672 dwCount = 1;
2673 rect.u1.x1 = 0;
2674 rect.u2.y1 = 0;
2675 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2676 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2677 lpRects = &rect;
2680 /* Clears the screen */
2681 ENTER_GL();
2683 if (dwFlags & D3DCLEAR_TARGET) {
2684 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2685 /* TODO: optimize here the case where Clear changes all the screen... */
2686 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2688 glThis->state[buffer_type] = SURFACE_GL;
2691 if (dwFlags & D3DCLEAR_ZBUFFER) {
2692 bitfield |= GL_DEPTH_BUFFER_BIT;
2693 if (glThis->depth_mask == FALSE) {
2694 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2696 if (dvZ != glThis->prev_clear_Z) {
2697 glClearDepth(dvZ);
2698 glThis->prev_clear_Z = dvZ;
2700 TRACE(" depth value : %f\n", dvZ);
2702 if (dwFlags & D3DCLEAR_STENCIL) {
2703 bitfield |= GL_STENCIL_BUFFER_BIT;
2704 if (dwStencil != glThis->prev_clear_stencil) {
2705 glClearStencil(dwStencil);
2706 glThis->prev_clear_stencil = dwStencil;
2708 TRACE(" stencil value : %ld\n", dwStencil);
2710 if (dwFlags & D3DCLEAR_TARGET) {
2711 bitfield |= GL_COLOR_BUFFER_BIT;
2712 if (dwColor != glThis->prev_clear_color) {
2713 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2714 ((dwColor >> 8) & 0xFF) / 255.0,
2715 ((dwColor >> 0) & 0xFF) / 255.0,
2716 ((dwColor >> 24) & 0xFF) / 255.0);
2717 glThis->prev_clear_color = dwColor;
2719 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2722 glEnable(GL_SCISSOR_TEST);
2723 for (i = 0; i < dwCount; i++) {
2724 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2725 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2726 glClear(bitfield);
2728 glDisable(GL_SCISSOR_TEST);
2730 if (dwFlags & D3DCLEAR_ZBUFFER) {
2731 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2734 LEAVE_GL();
2736 return DD_OK;
2739 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2740 DWORD dwCount,
2741 LPD3DRECT lpRects,
2742 DWORD dwFlags,
2743 DWORD dwColor,
2744 D3DVALUE dvZ,
2745 DWORD dwStencil)
2747 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2750 static HRESULT
2751 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2752 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2754 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2755 WINE_GL_BUFFER_TYPE buffer_type;
2757 /* First check if we BLT to the backbuffer... */
2758 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2759 buffer_type = WINE_GL_BUFFER_BACK;
2760 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2761 buffer_type = WINE_GL_BUFFER_FRONT;
2762 } else {
2763 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2764 return DDERR_INVALIDPARAMS;
2767 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2768 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2769 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2770 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2771 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2772 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2773 * GL to do it.
2775 return DDERR_INVALIDPARAMS;
2777 *buffer_type_p = buffer_type;
2779 return DD_OK;
2782 HRESULT
2783 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2784 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2785 DWORD dwFlags, LPDDBLTFX lpbltfx)
2787 WINE_GL_BUFFER_TYPE buffer_type;
2788 D3DRECT rect;
2790 if (rdst) {
2791 rect.u1.x1 = rdst->left;
2792 rect.u2.y1 = rdst->top;
2793 rect.u3.x2 = rdst->right;
2794 rect.u4.y2 = rdst->bottom;
2795 } else {
2796 rect.u1.x1 = 0;
2797 rect.u2.y1 = 0;
2798 rect.u3.x2 = This->surface_desc.dwWidth;
2799 rect.u4.y2 = This->surface_desc.dwHeight;
2802 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2804 if (dwFlags & DDBLT_COLORFILL) {
2805 /* This is easy to handle for the D3D Device... */
2806 DWORD color;
2807 GLenum prev_draw;
2809 /* The color as given in the Blt function is in the format of the frame-buffer...
2810 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2812 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2813 if (This->palette) {
2814 color = ((0xFF000000) |
2815 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2816 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2817 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2818 } else {
2819 color = 0xFF000000;
2821 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2822 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2823 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2824 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2825 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2826 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2827 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2828 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2829 color = 0xFFFFFFFF;
2830 } else {
2831 color = ((0xFF000000) |
2832 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2833 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2834 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2836 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2837 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2838 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2839 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2840 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2841 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2842 } else {
2843 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2844 return DDERR_INVALIDPARAMS;
2846 } else {
2847 ERR("Wrong surface type for BLT override !\n");
2848 return DDERR_INVALIDPARAMS;
2851 TRACE(" executing D3D Device override.\n");
2853 ENTER_GL();
2855 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2856 if (buffer_type == WINE_GL_BUFFER_FRONT)
2857 glDrawBuffer(GL_FRONT);
2858 else
2859 glDrawBuffer(GL_BACK);
2861 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2863 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2864 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2865 glDrawBuffer(prev_draw);
2867 LEAVE_GL();
2869 return DD_OK;
2870 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
2871 /* Normal blit without any special case... */
2872 if (src != NULL) {
2873 /* And which has a SRC surface */
2874 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2876 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
2877 (src_impl->d3ddevice == This->d3ddevice) &&
2878 ((dwFlags & DDBLT_KEYSRC) == 0)) {
2879 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
2880 D3DRECT src_rect;
2881 int width, height;
2882 GLenum prev_draw;
2883 WINE_GL_BUFFER_TYPE src_buffer_type;
2884 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2885 BOOLEAN initial;
2886 DWORD opt_bitmap;
2887 int x, y;
2889 if (rsrc) {
2890 src_rect.u1.x1 = rsrc->left;
2891 src_rect.u2.y1 = rsrc->top;
2892 src_rect.u3.x2 = rsrc->right;
2893 src_rect.u4.y2 = rsrc->bottom;
2894 } else {
2895 src_rect.u1.x1 = 0;
2896 src_rect.u2.y1 = 0;
2897 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
2898 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
2901 width = src_rect.u3.x2 - src_rect.u1.x1;
2902 height = src_rect.u4.y2 - src_rect.u2.y1;
2904 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
2905 (height != (rect.u4.y2 - rect.u2.y1))) {
2906 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
2907 return DDERR_INVALIDPARAMS;
2910 /* First check if we BLT from the backbuffer... */
2911 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2912 src_buffer_type = WINE_GL_BUFFER_BACK;
2913 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2914 src_buffer_type = WINE_GL_BUFFER_FRONT;
2915 } else {
2916 ERR("Unexpected case in direct buffer to buffer copy !\n");
2917 return DDERR_INVALIDPARAMS;
2920 TRACE(" using direct buffer to buffer copy.\n");
2922 ENTER_GL();
2924 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
2926 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
2927 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2928 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
2929 LEAVE_GL();
2930 return DDERR_INVALIDPARAMS;
2933 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2934 if (buffer_type == WINE_GL_BUFFER_FRONT)
2935 glDrawBuffer(GL_FRONT);
2936 else
2937 glDrawBuffer(GL_BACK);
2939 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
2940 glReadBuffer(GL_FRONT);
2941 else
2942 glReadBuffer(GL_BACK);
2944 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
2945 And directly re-draws this on the destination buffer. */
2946 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
2947 int get_height;
2949 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
2950 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
2951 else
2952 get_height = UNLOCK_TEX_SIZE;
2954 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
2955 int get_width;
2957 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
2958 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
2959 else
2960 get_width = UNLOCK_TEX_SIZE;
2962 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2963 0, UNLOCK_TEX_SIZE - get_height,
2964 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
2965 get_width, get_height);
2967 glBegin(GL_QUADS);
2968 glTexCoord2f(0.0, 0.0);
2969 glVertex3d(rect.u1.x1 + x,
2970 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2971 0.5);
2972 glTexCoord2f(1.0, 0.0);
2973 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2974 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2975 0.5);
2976 glTexCoord2f(1.0, 1.0);
2977 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2978 rect.u2.y1 + y,
2979 0.5);
2980 glTexCoord2f(0.0, 1.0);
2981 glVertex3d(rect.u1.x1 + x,
2982 rect.u2.y1 + y,
2983 0.5);
2984 glEnd();
2988 upload_surface_to_tex_memory_release();
2989 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
2991 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2992 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2993 glDrawBuffer(prev_draw);
2995 LEAVE_GL();
2997 return DD_OK;
2998 } else {
2999 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3000 (this prevents calling glReadPixels) */
3001 D3DRECT src_rect;
3002 int width, height;
3003 GLenum prev_draw;
3004 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3005 BOOLEAN initial;
3006 DWORD opt_bitmap;
3007 int x, y;
3008 double x_stretch, y_stretch;
3010 if (rsrc) {
3011 src_rect.u1.x1 = rsrc->left;
3012 src_rect.u2.y1 = rsrc->top;
3013 src_rect.u3.x2 = rsrc->right;
3014 src_rect.u4.y2 = rsrc->bottom;
3015 } else {
3016 src_rect.u1.x1 = 0;
3017 src_rect.u2.y1 = 0;
3018 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
3019 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
3022 width = src_rect.u3.x2 - src_rect.u1.x1;
3023 height = src_rect.u4.y2 - src_rect.u2.y1;
3025 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
3026 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
3028 TRACE(" using memory to buffer Blt overide.\n");
3030 ENTER_GL();
3032 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
3034 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3035 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3036 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3037 LEAVE_GL();
3038 return DDERR_INVALIDPARAMS;
3041 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3042 if (buffer_type == WINE_GL_BUFFER_FRONT)
3043 glDrawBuffer(GL_FRONT);
3044 else
3045 glDrawBuffer(GL_BACK);
3047 /* Now the serious stuff happens. This is basically the same code that for the memory
3048 flush to frame buffer ... with stretching and different rectangles added :-) */
3049 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3050 RECT flush_rect;
3052 flush_rect.top = src_rect.u2.y1 + y;
3053 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
3054 src_rect.u4.y2 :
3055 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
3057 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3058 flush_rect.left = src_rect.u1.x1 + x;
3059 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
3060 src_rect.u3.x2 :
3061 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
3063 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3065 glBegin(GL_QUADS);
3066 glTexCoord2f(0.0, 0.0);
3067 glVertex3d(rect.u1.x1 + (x * x_stretch),
3068 rect.u2.y1 + (y * y_stretch),
3069 0.5);
3070 glTexCoord2f(1.0, 0.0);
3071 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3072 rect.u2.y1 + (y * y_stretch),
3073 0.5);
3074 glTexCoord2f(1.0, 1.0);
3075 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3076 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3077 0.5);
3078 glTexCoord2f(0.0, 1.0);
3079 glVertex3d(rect.u1.x1 + (x * x_stretch),
3080 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3081 0.5);
3082 glEnd();
3086 upload_surface_to_tex_memory_release();
3087 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3089 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3090 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3091 glDrawBuffer(prev_draw);
3093 LEAVE_GL();
3095 return DD_OK;
3099 return DDERR_INVALIDPARAMS;
3102 HRESULT
3103 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3104 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3105 LPRECT rsrc, DWORD trans)
3107 RECT rsrc2;
3108 RECT rdst;
3109 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3110 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3111 WINE_GL_BUFFER_TYPE buffer_type;
3112 GLenum prev_draw;
3113 DWORD opt_bitmap;
3114 BOOLEAN initial;
3115 int width, height, x, y;
3117 /* Cannot support DSTCOLORKEY blitting... */
3118 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3120 if (rsrc == NULL) {
3121 WARN("rsrc is NULL - getting the whole surface !!\n");
3122 rsrc = &rsrc2;
3123 rsrc->left = rsrc->top = 0;
3124 rsrc->right = src_impl->surface_desc.dwWidth;
3125 rsrc->bottom = src_impl->surface_desc.dwHeight;
3126 } else {
3127 rsrc2 = *rsrc;
3128 rsrc = &rsrc2;
3131 rdst.left = dstx;
3132 rdst.top = dsty;
3133 rdst.right = dstx + (rsrc->right - rsrc->left);
3134 if (rdst.right > This->surface_desc.dwWidth) {
3135 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3136 rdst.right = This->surface_desc.dwWidth;
3138 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3139 if (rdst.bottom > This->surface_desc.dwHeight) {
3140 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3141 rdst.bottom = This->surface_desc.dwHeight;
3144 width = rsrc->right - rsrc->left;
3145 height = rsrc->bottom - rsrc->top;
3147 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3149 TRACE(" using BltFast memory to frame buffer overide.\n");
3151 ENTER_GL();
3153 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3155 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3156 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3157 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3158 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3159 LEAVE_GL();
3160 return DDERR_INVALIDPARAMS;
3163 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3164 if (buffer_type == WINE_GL_BUFFER_FRONT)
3165 glDrawBuffer(GL_FRONT);
3166 else
3167 glDrawBuffer(GL_BACK);
3169 /* Now the serious stuff happens. This is basically the same code that for the memory
3170 flush to frame buffer but with different rectangles for source and destination :-) */
3171 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3172 RECT flush_rect;
3174 flush_rect.top = rsrc->top + y;
3175 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3176 rsrc->bottom :
3177 (rsrc->top + y + UNLOCK_TEX_SIZE));
3179 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3180 flush_rect.left = rsrc->left + x;
3181 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3182 rsrc->right :
3183 (rsrc->left + x + UNLOCK_TEX_SIZE));
3185 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3187 glBegin(GL_QUADS);
3188 glTexCoord2f(0.0, 0.0);
3189 glVertex3d(rdst.left + x,
3190 rdst.top + y,
3191 0.5);
3192 glTexCoord2f(1.0, 0.0);
3193 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3194 rdst.top + y,
3195 0.5);
3196 glTexCoord2f(1.0, 1.0);
3197 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3198 rdst.top + (y + UNLOCK_TEX_SIZE),
3199 0.5);
3200 glTexCoord2f(0.0, 1.0);
3201 glVertex3d(rdst.left + x,
3202 rdst.top + (y + UNLOCK_TEX_SIZE),
3203 0.5);
3204 glEnd();
3208 upload_surface_to_tex_memory_release();
3209 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3211 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3212 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3213 glDrawBuffer(prev_draw);
3215 LEAVE_GL();
3217 return DD_OK;
3220 void
3221 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3223 GLfloat height, width;
3224 GLfloat trans_mat[16];
3226 TRACE("(%p)\n", This);
3228 width = This->surface->surface_desc.dwWidth;
3229 height = This->surface->surface_desc.dwHeight;
3231 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3232 to OpenGL screen coordinates (ie the upper left corner is not the same).
3233 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
3234 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
3235 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3236 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3237 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 2.0; trans_mat[14] = -1.0;
3238 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3240 ENTER_GL();
3241 glMatrixMode(GL_MODELVIEW);
3242 glLoadIdentity();
3243 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3244 Correctness Tips section).
3246 Basically, from what I understood, if the game does not filter the font texture,
3247 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3248 one and we will have strange artifacts (as the rounding and stuff may give different results
3249 for different pixels, ie sometimes take the left pixel, sometimes the right).
3251 glTranslatef(0.375, 0.375, 0);
3252 glMatrixMode(GL_PROJECTION);
3253 glLoadMatrixf(trans_mat);
3254 LEAVE_GL();
3257 void
3258 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3259 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3261 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3263 ENTER_GL();
3264 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3265 glMatrixMode(GL_MODELVIEW);
3266 glLoadMatrixf((float *) view_mat);
3268 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3269 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3270 GLint i;
3271 DWORD runner;
3272 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3273 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3274 GLdouble plane[4];
3276 plane[0] = This->clipping_planes[i].plane[0];
3277 plane[1] = This->clipping_planes[i].plane[1];
3278 plane[2] = This->clipping_planes[i].plane[2];
3279 plane[3] = This->clipping_planes[i].plane[3];
3281 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3285 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3286 GLint i;
3287 DWORD runner;
3289 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3290 if (runner & This->active_lights) {
3291 switch (This->light_parameters[i].dltType) {
3292 case D3DLIGHT_DIRECTIONAL: {
3293 float direction[4];
3294 float cut_off = 180.0;
3296 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3297 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3298 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3299 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3301 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3302 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3303 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3304 direction[3] = 0.0;
3305 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3306 } break;
3308 case D3DLIGHT_POINT: {
3309 float position[4];
3310 float cut_off = 180.0;
3312 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3313 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3314 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3315 position[0] = This->light_parameters[i].dvPosition.u1.x;
3316 position[1] = This->light_parameters[i].dvPosition.u2.y;
3317 position[2] = This->light_parameters[i].dvPosition.u3.z;
3318 position[3] = 1.0;
3319 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3320 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3321 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3322 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3323 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3324 } break;
3326 case D3DLIGHT_SPOT: {
3327 float direction[4];
3328 float position[4];
3329 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3331 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3332 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3333 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3335 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3336 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3337 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3338 direction[3] = 0.0;
3339 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3340 position[0] = This->light_parameters[i].dvPosition.u1.x;
3341 position[1] = This->light_parameters[i].dvPosition.u2.y;
3342 position[2] = This->light_parameters[i].dvPosition.u3.z;
3343 position[3] = 1.0;
3344 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3345 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3346 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3347 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3348 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3349 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3350 } break;
3352 default:
3353 /* No warning here as it's already done at light setting */
3354 break;
3360 glMultMatrixf((float *) world_mat);
3362 if ((matrices & PROJMAT_CHANGED) != 0) {
3363 glMatrixMode(GL_PROJECTION);
3364 glLoadMatrixf((float *) proj_mat);
3366 LEAVE_GL();
3369 void
3370 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3372 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3373 DWORD tex_mat, tex_stage;
3375 TRACE("(%p,%08lx)\n", This, matrices);
3377 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3378 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3379 /* This will force an update of the transform state at the next drawing. */
3380 glThis->transform_state = GL_TRANSFORM_NONE;
3383 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3384 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3386 ENTER_GL();
3387 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3388 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3389 if (matrices & tex_mat) {
3390 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3391 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3393 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3394 if (glThis->current_active_tex_unit != unit) {
3395 GL_extensions.glActiveTexture(unit);
3396 glThis->current_active_tex_unit = unit;
3398 glMatrixMode(GL_TEXTURE);
3399 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3401 This->tex_mat_is_identity[tex_stage] = is_identity;
3402 } else {
3403 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3404 if (glThis->current_active_tex_unit != unit) {
3405 GL_extensions.glActiveTexture(unit);
3406 glThis->current_active_tex_unit = unit;
3408 glMatrixMode(GL_TEXTURE);
3409 glLoadIdentity();
3410 This->tex_mat_is_identity[tex_stage] = TRUE;
3415 LEAVE_GL();
3419 /* TODO for both these functions :
3420 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3421 by other OpenGL code in D3D
3422 - handle the case where no 'Begin / EndScene' was done between two locks
3423 - handle the rectangles in the unlock too
3424 - handle pitch correctly...
3426 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3428 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3429 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3430 WINE_GL_BUFFER_TYPE buffer_type;
3431 RECT loc_rect;
3433 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3434 buffer_type = WINE_GL_BUFFER_FRONT;
3435 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3436 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3437 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3439 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3440 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3441 buffer_type = WINE_GL_BUFFER_BACK;
3442 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3443 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3444 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3446 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3447 } else {
3448 ERR("Wrong surface type for locking !\n");
3449 return;
3452 if (pRect == NULL) {
3453 loc_rect.top = 0;
3454 loc_rect.left = 0;
3455 loc_rect.bottom = This->surface_desc.dwHeight;
3456 loc_rect.right = This->surface_desc.dwWidth;
3457 pRect = &loc_rect;
3460 /* Try to acquire the device critical section */
3461 EnterCriticalSection(&(d3d_dev->crit));
3463 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3464 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3465 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3467 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3469 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3470 /* Check if the new rectangle is in the previous one or not.
3471 If it is not, flush first the previous locks on screen.
3473 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3474 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3475 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3476 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3477 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3478 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3479 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3480 pRect->left, pRect->top, pRect->right, pRect->bottom,
3481 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3482 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3483 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3485 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3486 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3488 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3489 } else {
3490 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3493 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3494 /* If the surface is already in memory, no need to do anything here... */
3495 GLenum buffer_format;
3496 GLenum buffer_color;
3497 int y;
3498 char *dst;
3500 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3501 pRect->left, pRect->top, pRect->right, pRect->bottom);
3503 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3504 may only write to the device... But when we will blit it back to the screen, we need
3505 also to blit correctly the parts the application did not overwrite... */
3507 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3508 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3509 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3510 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3511 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3512 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3513 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3514 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3515 buffer_color = GL_RGB;
3516 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3517 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3518 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3519 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3520 buffer_format = GL_UNSIGNED_BYTE;
3521 buffer_color = GL_RGB;
3522 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3523 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3524 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3525 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3526 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3527 buffer_color = GL_BGRA;
3528 } else {
3529 ERR(" unsupported pixel format at device locking.\n");
3530 return;
3532 } else {
3533 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3534 return;
3537 ENTER_GL();
3539 if (buffer_type == WINE_GL_BUFFER_FRONT)
3540 /* Application wants to lock the front buffer */
3541 glReadBuffer(GL_FRONT);
3542 else
3543 /* Application wants to lock the back buffer */
3544 glReadBuffer(GL_BACK);
3546 dst = ((char *)This->surface_desc.lpSurface) +
3547 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3548 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3549 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3550 y--) {
3551 glReadPixels(pRect->left, y,
3552 pRect->right - pRect->left, 1,
3553 buffer_color, buffer_format, dst);
3554 dst += This->surface_desc.u1.lPitch;
3557 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3559 #if 0
3560 /* I keep this code here as it's very useful to debug :-) */
3562 static int flush_count = 0;
3563 char buf[128];
3564 FILE *f;
3566 if ((++flush_count % 50) == 0) {
3567 sprintf(buf, "lock_%06d.pnm", flush_count);
3568 f = fopen(buf, "wb");
3569 DDRAW_dump_surface_to_disk(This, f);
3572 #endif
3574 LEAVE_GL();
3578 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3579 RECT loc_rect;
3580 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3581 int x, y;
3582 BOOLEAN initial;
3583 DWORD opt_bitmap;
3585 /* Note : no need here to lock the 'device critical section' as we are already protected by
3586 the GL critical section. */
3588 if (pRect == NULL) {
3589 loc_rect.top = 0;
3590 loc_rect.left = 0;
3591 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3592 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3593 pRect = &loc_rect;
3596 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3598 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3600 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3601 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3602 ERR(" unsupported pixel format at frame buffer flush.\n");
3603 return;
3606 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3607 RECT flush_rect;
3609 flush_rect.top = y;
3610 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3612 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3613 /* First, upload the texture... */
3614 flush_rect.left = x;
3615 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3617 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3619 glBegin(GL_QUADS);
3620 glTexCoord2f(0.0, 0.0);
3621 glVertex3d(x, y, 0.5);
3622 glTexCoord2f(1.0, 0.0);
3623 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3624 glTexCoord2f(1.0, 1.0);
3625 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3626 glTexCoord2f(0.0, 1.0);
3627 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3628 glEnd();
3632 upload_surface_to_tex_memory_release();
3633 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3635 #if 0
3636 /* I keep this code here as it's very useful to debug :-) */
3638 static int flush_count = 0;
3639 char buf[128];
3640 FILE *f;
3642 if ((++flush_count % 50) == 0) {
3643 sprintf(buf, "flush_%06d.pnm", flush_count);
3644 f = fopen(buf, "wb");
3645 DDRAW_dump_surface_to_disk(surf, f);
3648 #endif
3651 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3653 WINE_GL_BUFFER_TYPE buffer_type;
3654 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3655 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3657 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3658 buffer_type = WINE_GL_BUFFER_FRONT;
3659 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3660 buffer_type = WINE_GL_BUFFER_BACK;
3661 } else {
3662 ERR("Wrong surface type for locking !\n");
3663 return;
3666 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3667 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3668 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3670 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3672 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3673 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3674 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3675 GLenum prev_draw;
3677 TRACE(" flushing front buffer immediatly on screen.\n");
3679 ENTER_GL();
3680 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3681 glDrawBuffer(GL_FRONT);
3682 /* Note: we do not use the application provided lock rectangle but our own stored at
3683 lock time. This is because in old D3D versions, the 'lock' parameter did not
3684 exist.
3686 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]);
3687 glDrawBuffer(prev_draw);
3688 LEAVE_GL();
3689 } else {
3690 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3694 /* And 'frees' the device critical section */
3695 LeaveCriticalSection(&(d3d_dev->crit));
3698 static void
3699 apply_texture_state(IDirect3DDeviceImpl *This)
3701 int stage, state;
3703 /* Initialize texture stages states */
3704 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3705 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3706 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3707 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3708 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3714 HRESULT
3715 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface)
3717 IDirect3DDeviceImpl *object;
3718 IDirect3DDeviceGLImpl *gl_object;
3719 IDirectDrawSurfaceImpl *surf;
3720 HDC device_context;
3721 XVisualInfo *vis;
3722 int num;
3723 int tex_num;
3724 XVisualInfo template;
3725 GLenum buffer = GL_FRONT;
3726 int light;
3728 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3729 if (object == NULL) return DDERR_OUTOFMEMORY;
3731 gl_object = (IDirect3DDeviceGLImpl *) object;
3733 object->ref = 1;
3734 object->d3d = d3d;
3735 object->surface = surface;
3736 object->set_context = set_context;
3737 object->clear = d3ddevice_clear_back;
3738 object->set_matrices = d3ddevice_set_matrices;
3739 object->matrices_updated = d3ddevice_matrices_updated;
3740 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3742 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3744 InitializeCriticalSection(&(object->crit));
3746 TRACE(" device critical section : %p\n", &(object->crit));
3748 device_context = GetDC(surface->ddraw_owner->window);
3749 gl_object->display = get_display(device_context);
3750 gl_object->drawable = get_drawable(device_context);
3751 ReleaseDC(surface->ddraw_owner->window,device_context);
3753 ENTER_GL();
3754 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3755 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3756 if (vis == NULL) {
3757 HeapFree(GetProcessHeap(), 0, object);
3758 ERR("No visual found !\n");
3759 LEAVE_GL();
3760 return DDERR_INVALIDPARAMS;
3761 } else {
3762 TRACE(" visual found\n");
3765 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3766 NULL, GL_TRUE);
3768 if (gl_object->gl_context == NULL) {
3769 HeapFree(GetProcessHeap(), 0, object);
3770 ERR("Error in context creation !\n");
3771 LEAVE_GL();
3772 return DDERR_INVALIDPARAMS;
3773 } else {
3774 TRACE(" context created (%p)\n", gl_object->gl_context);
3777 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3778 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3779 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3780 surf->aux_ctx = (LPVOID) object;
3781 surf->aux_data = (LPVOID) gl_object->drawable;
3782 surf->aux_flip = opengl_flip;
3783 buffer = GL_BACK;
3784 break;
3787 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3788 if (surf == NULL) {
3789 TRACE(" no double buffering : drawing on the front buffer\n");
3790 buffer = GL_FRONT;
3793 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3794 IDirectDrawSurfaceImpl *surf2;
3795 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3796 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3797 TRACE(" checking surface %p :", surf2);
3798 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3799 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3800 /* Override the Lock / Unlock function for all these surfaces */
3801 surf2->lock_update_prev = surf2->lock_update;
3802 surf2->lock_update = d3ddevice_lock_update;
3803 surf2->unlock_update_prev = surf2->unlock_update;
3804 surf2->unlock_update = d3ddevice_unlock_update;
3805 /* And install also the blt / bltfast overrides */
3806 surf2->aux_blt = d3ddevice_blt;
3807 surf2->aux_bltfast = d3ddevice_bltfast;
3809 TRACE(" overiding direct surface access.\n");
3810 } else {
3811 TRACE(" no overide.\n");
3813 surf2->d3ddevice = object;
3817 /* Set the various light parameters */
3818 for (light = 0; light < MAX_LIGHTS; light++) {
3819 /* Only set the fields that are not zero-created */
3820 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3821 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3822 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3823 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3824 object->light_parameters[light].dvDirection.u3.z = 1.0;
3827 /* Allocate memory for the matrices */
3828 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3829 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3830 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3831 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3832 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3833 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3834 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3835 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3836 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3837 object->tex_mat_is_identity[tex_num] = TRUE;
3840 /* Initialisation */
3841 TRACE(" setting current context\n");
3842 object->set_context(object);
3843 TRACE(" current context set\n");
3845 /* allocate the clipping planes */
3846 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
3847 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3849 glHint(GL_FOG_HINT,GL_NICEST);
3851 /* Initialize the various GL contexts to be in sync with what we store locally */
3852 glClearDepth(0.0);
3853 glClearStencil(0);
3854 glClearColor(0.0, 0.0, 0.0, 0.0);
3855 glDepthMask(GL_TRUE);
3856 gl_object->depth_mask = TRUE;
3857 glEnable(GL_DEPTH_TEST);
3858 gl_object->depth_test = TRUE;
3859 glDisable(GL_ALPHA_TEST);
3860 glDisable(GL_STENCIL_TEST);
3861 glDisable(GL_CULL_FACE);
3862 glDisable(GL_LIGHTING);
3863 glDisable(GL_BLEND);
3864 glDisable(GL_FOG);
3865 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3866 gl_object->current_tex_env = GL_REPLACE;
3867 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
3868 if (GL_extensions.glActiveTexture != NULL) {
3869 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
3872 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3873 glDrawBuffer(buffer);
3874 glReadBuffer(buffer);
3875 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3876 LEAVE_GL();
3878 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
3879 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
3881 /* fill_device_capabilities(d3d->ddraw); */
3883 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3884 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3885 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3886 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3888 *obj = object;
3890 TRACE(" creating implementation at %p.\n", *obj);
3892 /* And finally warn D3D that this device is now present */
3893 object->d3d->d3d_added_device(object->d3d, object);
3895 /* FIXME: Should handle other versions than just 7 */
3896 InitDefaultStateBlock(&object->state_block, 7);
3897 /* Apply default render state and texture stage state values */
3898 apply_render_state(object, &object->state_block);
3899 apply_texture_state(object);
3901 /* And fill the fog table with the default fog value */
3902 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3904 return DD_OK;
3907 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
3909 pc->dwSize = sizeof(*pc);
3910 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
3911 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
3912 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
3913 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
3914 D3DPRASTERCAPS_ZFOG;
3915 if (GL_extensions.mipmap_lodbias == TRUE) {
3916 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
3918 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3919 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3920 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
3921 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3922 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3923 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
3924 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3925 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3926 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3927 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3928 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
3929 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
3930 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
3931 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
3932 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
3933 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
3934 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
3935 D3DPTFILTERCAPS_MIPFPOINT;
3936 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
3937 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
3938 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
3939 if (GL_extensions.mirrored_repeat == TRUE) {
3940 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
3942 pc->dwStippleWidth = 32;
3943 pc->dwStippleHeight = 32;
3946 static void fill_caps(void)
3948 GLint max_clip_planes;
3949 GLint depth_bits;
3951 /* Fill first all the fields with default values which will be overriden later on with
3952 correct ones from the GL code
3954 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
3955 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
3956 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3957 /* D3D 7 capabilities */
3958 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
3959 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
3960 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
3961 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
3962 opengl_device_caps.dwMinTextureWidth = 1;
3963 opengl_device_caps.dwMinTextureHeight = 1;
3964 opengl_device_caps.dwMaxTextureWidth = 1024;
3965 opengl_device_caps.dwMaxTextureHeight = 1024;
3966 opengl_device_caps.dwMaxTextureRepeat = 16;
3967 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
3968 opengl_device_caps.dwMaxAnisotropy = 0;
3969 opengl_device_caps.dvGuardBandLeft = 0.0;
3970 opengl_device_caps.dvGuardBandRight = 0.0;
3971 opengl_device_caps.dvGuardBandTop = 0.0;
3972 opengl_device_caps.dvGuardBandBottom = 0.0;
3973 opengl_device_caps.dvExtentsAdjust = 0.0;
3974 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
3975 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
3976 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
3977 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
3978 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
3979 if (GL_extensions.max_texture_units != 0) {
3980 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
3981 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
3982 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
3983 } else {
3984 opengl_device_caps.wMaxTextureBlendStages = 1;
3985 opengl_device_caps.wMaxSimultaneousTextures = 1;
3986 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
3988 opengl_device_caps.dwMaxActiveLights = 16;
3989 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
3990 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
3991 opengl_device_caps.wMaxUserClipPlanes = 1;
3992 opengl_device_caps.wMaxVertexBlendMatrices = 0;
3993 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
3994 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
3995 opengl_device_caps.dwReserved1 = 0;
3996 opengl_device_caps.dwReserved2 = 0;
3997 opengl_device_caps.dwReserved3 = 0;
3998 opengl_device_caps.dwReserved4 = 0;
4000 /* And now some GL overides :-) */
4001 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
4002 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
4003 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
4004 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
4006 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
4007 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
4009 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
4010 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
4011 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
4013 glGetIntegerv(GL_DEPTH_BITS, &depth_bits);
4014 TRACE(": Z bits = %d\n", depth_bits);
4015 switch (depth_bits) {
4016 case 16: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16; break;
4017 case 24: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24; break;
4018 case 32:
4019 default: opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32; break;
4023 BOOL
4024 d3ddevice_init_at_startup(void *gl_handle)
4026 XVisualInfo template;
4027 XVisualInfo *vis;
4028 HDC device_context;
4029 Display *display;
4030 Visual *visual;
4031 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4032 XWindowAttributes win_attr;
4033 GLXContext gl_context;
4034 int num;
4035 const char *glExtensions;
4036 const char *glVersion;
4037 const char *glXExtensions = NULL;
4038 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
4039 int major, minor, patch;
4041 TRACE("Initializing GL...\n");
4043 /* Get a default rendering context to have the 'caps' function query some info from GL */
4044 device_context = GetDC(0);
4045 display = get_display(device_context);
4046 ReleaseDC(0, device_context);
4048 ENTER_GL();
4049 if (XGetWindowAttributes(display, drawable, &win_attr)) {
4050 visual = win_attr.visual;
4051 } else {
4052 visual = DefaultVisual(display, DefaultScreen(display));
4054 template.visualid = XVisualIDFromVisual(visual);
4055 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
4056 if (vis == NULL) {
4057 LEAVE_GL();
4058 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4059 return FALSE;
4061 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
4063 if (gl_context == NULL) {
4064 LEAVE_GL();
4065 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4066 return FALSE;
4068 if (glXMakeCurrent(display, drawable, gl_context) == False) {
4069 glXDestroyContext(display, gl_context);
4070 LEAVE_GL();
4071 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4072 return FALSE;
4075 /* Then, query all extensions */
4076 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display));
4077 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
4078 glVersion = (const char *) glGetString(GL_VERSION);
4079 if ((glXExtensions != NULL) && (gl_handle != NULL) && (strstr(glXExtensions, "GLX_ARB_get_proc_address"))) {
4080 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4083 /* Parse the GL version string */
4084 sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4085 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4087 /* And starts to fill the extension context properly */
4088 memset(&GL_extensions, 0, sizeof(GL_extensions));
4089 TRACE("GL supports following extensions used by Wine :\n");
4091 /* Mirrored Repeat extension :
4092 - GL_ARB_texture_mirrored_repeat
4093 - GL_IBM_texture_mirrored_repeat
4094 - GL >= 1.4
4096 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4097 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4098 (major > 1) ||
4099 ((major == 1) && (minor >= 4))) {
4100 TRACE(" - mirrored repeat\n");
4101 GL_extensions.mirrored_repeat = TRUE;
4104 /* Texture LOD Bias :
4105 - GL_EXT_texture_lod_bias
4107 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4108 TRACE(" - texture lod bias\n");
4109 GL_extensions.mipmap_lodbias = TRUE;
4112 /* For all subsequent extensions, we need glXGetProcAddress */
4113 if (pglXGetProcAddressARB != NULL) {
4114 /* Multi-texturing :
4115 - GL_ARB_multitexture
4116 - GL >= 1.2.1
4118 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4119 (major > 1) ||
4120 ((major == 1) && (minor > 2)) ||
4121 ((major == 1) && (minor == 2) && (patch >= 1))) {
4122 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4123 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4124 /* We query the ARB version to be the most portable we can... */
4125 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4126 GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
4130 /* Fill the D3D capabilities according to what GL tells us... */
4131 fill_caps();
4133 /* And frees this now-useless context */
4134 glXMakeCurrent(display, None, NULL);
4135 glXDestroyContext(display, gl_context);
4136 LEAVE_GL();
4138 return TRUE;