2 * Copyright (c) 1998 Lionel ULMER
4 * This file contains the MESA implementation of all the D3D devices that
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
23 #include "wine/port.h"
29 #define NONAMELESSUNION
30 #define NONAMELESSSTRUCT
38 #include "wine/debug.h"
39 #include "wine/library.h"
41 #include "mesa_private.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 = {
62 { 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
65 const float id_mat[16] = {
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,
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 )
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;
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);
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);
121 glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
124 if (d3d_dev->tex_mat_is_identity[0] == FALSE) {
125 glMatrixMode(GL_TEXTURE);
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);
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);
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);
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);
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 )
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;
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);
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);
262 if (TRACE_ON(ddraw_fps)) {
263 LONGLONG current_time;
264 LONGLONG frame_duration;
265 QueryPerformanceCounter((LARGE_INTEGER *) ¤t_time);
267 if (prev_time != 0) {
268 LONGLONG total_time = 0;
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) {
281 if (valid_windows < NUMBER_OF_WINDOWS) {
283 tot_meas = valid_windows * MEASUREMENT_WINDOW;
284 for (i = 0; i < valid_windows; i++) {
285 total_time += perf_storage[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) {
300 perf_storage[current_window] = 0;
301 measurements_in_window = 0;
304 prev_time = current_time;
305 memset(perf_storage, 0, sizeof(perf_storage));
308 measurements_in_window = 0;
309 QueryPerformanceFrequency((LARGE_INTEGER *) &perf_freq);
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);
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);
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;
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);
395 /* It seems that enumerating the reference IID on Direct3D 1 games (AvP / Motoracer2) breaks them */
396 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice));
399 ret_value = cb((LPIID) &IID_IDirect3DRefDevice, "WINE Reference Direct3DX using OpenGL", device_name, &d1, &d2, context);
400 if (ret_value != D3DENUMRET_OK)
404 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL));
407 ret_value = cb((LPIID) &IID_D3DDEVICE_OpenGL, "WINE Direct3DX using OpenGL", device_name, &d1, &d2, context);
408 if (ret_value != D3DENUMRET_OK)
411 return D3DENUMRET_OK;
414 HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context)
416 D3DDEVICEDESC7 ddesc;
418 fill_opengl_caps_7(&ddesc);
420 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
422 return cb("WINE Direct3D7 using OpenGL", "Wine D3D7 device", &ddesc, context);
426 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface)
428 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
429 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
431 TRACE("(%p/%p)->() decrementing from %lu.\n", This, iface, This->ref);
432 if (!--(This->ref)) {
434 IDirectDrawSurfaceImpl *surface = This->surface, *surf;
436 /* Release texture associated with the device */
437 for (i = 0; i < MAX_TEXTURES; i++) {
438 if (This->current_texture[i] != NULL)
439 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[i], IDirectDrawSurface7));
440 HeapFree(GetProcessHeap(), 0, This->tex_mat[i]);
443 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
444 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
445 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
446 surf->aux_ctx = NULL;
447 surf->aux_data = NULL;
448 surf->aux_flip = NULL;
452 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
453 IDirectDrawSurfaceImpl *surf2;
454 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
455 for (; surf2 != NULL; surf2 = surf2->next_attached) {
456 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
457 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
458 /* Override the Lock / Unlock function for all these surfaces */
459 surf2->lock_update = surf2->lock_update_prev;
460 surf2->unlock_update = surf2->unlock_update_prev;
461 /* And install also the blt / bltfast overrides */
462 surf2->aux_blt = NULL;
463 surf2->aux_bltfast = NULL;
465 surf2->d3ddevice = NULL;
469 /* And warn the D3D object that this device is no longer active... */
470 This->d3d->d3d_removed_device(This->d3d, This);
472 HeapFree(GetProcessHeap(), 0, This->world_mat);
473 HeapFree(GetProcessHeap(), 0, This->view_mat);
474 HeapFree(GetProcessHeap(), 0, This->proj_mat);
476 if (glThis->surface_ptr)
477 HeapFree(GetProcessHeap(), 0, glThis->surface_ptr);
479 DeleteCriticalSection(&(This->crit));
482 if (glThis->unlock_tex)
483 glDeleteTextures(1, &(glThis->unlock_tex));
484 glXDestroyContext(glThis->display, glThis->gl_context);
486 HeapFree(GetProcessHeap(), 0, This->clipping_planes);
488 HeapFree(GetProcessHeap(), 0, This);
495 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface,
496 LPD3DDEVICEDESC lpD3DHWDevDesc,
497 LPD3DDEVICEDESC lpD3DHELDevDesc)
499 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
503 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DHWDevDesc, lpD3DHELDevDesc);
505 fill_opengl_caps(&desc);
506 dwSize = lpD3DHWDevDesc->dwSize;
507 memset(lpD3DHWDevDesc, 0, dwSize);
508 memcpy(lpD3DHWDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
510 dwSize = lpD3DHELDevDesc->dwSize;
511 memset(lpD3DHELDevDesc, 0, dwSize);
512 memcpy(lpD3DHELDevDesc, &desc, (dwSize <= desc.dwSize ? dwSize : desc.dwSize));
514 TRACE(" returning caps : (no dump function yet)\n");
519 static HRESULT enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1,
520 LPD3DENUMPIXELFORMATSCALLBACK cb_2,
524 LPDDPIXELFORMAT pformat;
526 /* Do the texture enumeration */
527 sdesc.dwSize = sizeof(DDSURFACEDESC);
528 sdesc.dwFlags = DDSD_PIXELFORMAT | DDSD_CAPS;
529 sdesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
530 pformat = &(sdesc.ddpfPixelFormat);
531 pformat->dwSize = sizeof(DDPIXELFORMAT);
532 pformat->dwFourCC = 0;
534 TRACE("Enumerating GL_RGBA unpacked (32)\n");
535 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
536 pformat->u1.dwRGBBitCount = 32;
537 pformat->u2.dwRBitMask = 0x00FF0000;
538 pformat->u3.dwGBitMask = 0x0000FF00;
539 pformat->u4.dwBBitMask = 0x000000FF;
540 pformat->u5.dwRGBAlphaBitMask = 0xFF000000;
541 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
542 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
544 TRACE("Enumerating GL_RGB unpacked (32)\n");
545 pformat->dwFlags = DDPF_RGB;
546 pformat->u1.dwRGBBitCount = 32;
547 pformat->u2.dwRBitMask = 0x00FF0000;
548 pformat->u3.dwGBitMask = 0x0000FF00;
549 pformat->u4.dwBBitMask = 0x000000FF;
550 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
551 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
552 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
554 TRACE("Enumerating GL_RGB unpacked (24)\n");
555 pformat->dwFlags = DDPF_RGB;
556 pformat->u1.dwRGBBitCount = 24;
557 pformat->u2.dwRBitMask = 0x00FF0000;
558 pformat->u3.dwGBitMask = 0x0000FF00;
559 pformat->u4.dwBBitMask = 0x000000FF;
560 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
561 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
562 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
564 /* Note : even if this is an 'emulated' texture format, it needs to be first
565 as some dumb applications seem to rely on that. */
566 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
567 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
568 pformat->u1.dwRGBBitCount = 16;
569 pformat->u2.dwRBitMask = 0x00007C00;
570 pformat->u3.dwGBitMask = 0x000003E0;
571 pformat->u4.dwBBitMask = 0x0000001F;
572 pformat->u5.dwRGBAlphaBitMask = 0x00008000;
573 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
574 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
576 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
577 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
578 pformat->u1.dwRGBBitCount = 16;
579 pformat->u2.dwRBitMask = 0x00000F00;
580 pformat->u3.dwGBitMask = 0x000000F0;
581 pformat->u4.dwBBitMask = 0x0000000F;
582 pformat->u5.dwRGBAlphaBitMask = 0x0000F000;
583 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
584 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
586 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
587 pformat->dwFlags = DDPF_RGB;
588 pformat->u1.dwRGBBitCount = 16;
589 pformat->u2.dwRBitMask = 0x0000F800;
590 pformat->u3.dwGBitMask = 0x000007E0;
591 pformat->u4.dwBBitMask = 0x0000001F;
592 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
593 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
594 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
596 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
597 pformat->dwFlags = DDPF_RGB;
598 pformat->u1.dwRGBBitCount = 16;
599 pformat->u2.dwRBitMask = 0x00007C00;
600 pformat->u3.dwGBitMask = 0x000003E0;
601 pformat->u4.dwBBitMask = 0x0000001F;
602 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
603 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
604 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
607 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
608 find enumerated, others the last one. And both want to have the ARGB one.
610 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
612 /* See argument about the RGBA format for 'packed' texture formats */
613 TRACE("Enumerating GL_RGBA unpacked (32)\n");
614 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
615 pformat->u1.dwRGBBitCount = 32;
616 pformat->u2.dwRBitMask = 0xFF000000;
617 pformat->u3.dwGBitMask = 0x00FF0000;
618 pformat->u4.dwBBitMask = 0x0000FF00;
619 pformat->u5.dwRGBAlphaBitMask = 0x000000FF;
620 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
621 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
623 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
624 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
625 pformat->u1.dwRGBBitCount = 16;
626 pformat->u2.dwRBitMask = 0x0000F000;
627 pformat->u3.dwGBitMask = 0x00000F00;
628 pformat->u4.dwBBitMask = 0x000000F0;
629 pformat->u5.dwRGBAlphaBitMask = 0x0000000F;
630 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
631 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
633 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
634 pformat->dwFlags = DDPF_RGB | DDPF_ALPHAPIXELS;
635 pformat->u1.dwRGBBitCount = 16;
636 pformat->u2.dwRBitMask = 0x0000F800;
637 pformat->u3.dwGBitMask = 0x000007C0;
638 pformat->u4.dwBBitMask = 0x0000003E;
639 pformat->u5.dwRGBAlphaBitMask = 0x00000001;
640 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
641 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
644 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
645 pformat->dwFlags = DDPF_RGB;
646 pformat->u1.dwRGBBitCount = 8;
647 pformat->u2.dwRBitMask = 0x000000E0;
648 pformat->u3.dwGBitMask = 0x0000001C;
649 pformat->u4.dwBBitMask = 0x00000003;
650 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
651 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
652 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
654 TRACE("Enumerating Paletted (8)\n");
655 pformat->dwFlags = DDPF_PALETTEINDEXED8;
656 pformat->u1.dwRGBBitCount = 8;
657 pformat->u2.dwRBitMask = 0x00000000;
658 pformat->u3.dwGBitMask = 0x00000000;
659 pformat->u4.dwBBitMask = 0x00000000;
660 pformat->u5.dwRGBAlphaBitMask = 0x00000000;
661 if (cb_1) if (cb_1(&sdesc , context) == 0) return DD_OK;
662 if (cb_2) if (cb_2(pformat, context) == 0) return DD_OK;
664 TRACE("End of enumeration\n");
670 d3ddevice_find(IDirectDrawImpl *d3d,
671 LPD3DFINDDEVICESEARCH lpD3DDFS,
672 LPD3DFINDDEVICERESULT lplpD3DDevice)
676 if ((lpD3DDFS->dwFlags & D3DFDS_COLORMODEL) &&
677 (lpD3DDFS->dcmColorModel != D3DCOLOR_RGB)) {
678 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
679 return DDERR_INVALIDPARAMS; /* No real idea what to return here :-) */
681 if (lpD3DDFS->dwFlags & D3DFDS_GUID) {
682 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS->guid)));
683 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL, &(lpD3DDFS->guid)) == 0) &&
684 (IsEqualGUID(&IID_IDirect3DHALDevice, &(lpD3DDFS->guid)) == 0) &&
685 (IsEqualGUID(&IID_IDirect3DRefDevice, &(lpD3DDFS->guid)) == 0)) {
686 TRACE(" no match for this GUID.\n");
687 return DDERR_INVALIDPARAMS;
691 /* Now return our own GUID */
692 lplpD3DDevice->guid = IID_D3DDEVICE_OpenGL;
693 fill_opengl_caps(&desc);
694 lplpD3DDevice->ddHwDesc = desc;
695 lplpD3DDevice->ddSwDesc = desc;
697 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
703 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface,
704 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc,
707 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
708 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumTextureProc, lpArg);
709 return enum_texture_format_OpenGL(lpD3DEnumTextureProc, NULL, lpArg);
713 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface,
714 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc,
717 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
718 TRACE("(%p/%p)->(%p,%p)\n", This, iface, lpD3DEnumPixelProc, lpArg);
719 return enum_texture_format_OpenGL(NULL, lpD3DEnumPixelProc, lpArg);
723 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface,
724 D3DRENDERSTATETYPE dwRenderStateType,
727 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
728 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwRenderStateType, dwRenderState);
730 /* Call the render state functions */
731 store_render_state(This, dwRenderStateType, dwRenderState, &This->state_block);
732 set_render_state(This, dwRenderStateType, &This->state_block);
738 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface,
739 D3DRENDERSTATETYPE dwRenderStateType,
740 LPDWORD lpdwRenderState)
742 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
743 TRACE("(%p/%p)->(%08x,%p)\n", This, iface, dwRenderStateType, lpdwRenderState);
745 /* Call the render state functions */
746 get_render_state(This, dwRenderStateType, lpdwRenderState, &This->state_block);
748 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType), *lpdwRenderState);
754 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
755 D3DLIGHTSTATETYPE dwLightStateType,
758 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
760 TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
762 if (!dwLightStateType && (dwLightStateType > D3DLIGHTSTATE_COLORVERTEX))
763 TRACE("Unexpected Light State Type\n");
764 return DDERR_INVALIDPARAMS;
766 if (dwLightStateType == D3DLIGHTSTATE_MATERIAL /* 1 */) {
767 IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
772 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
774 } else if (dwLightStateType == D3DLIGHTSTATE_COLORMODEL /* 3 */) {
775 switch (dwLightState) {
777 ERR("DDCOLOR_MONO should not happen!\n");
780 /* We are already in this mode */
783 ERR("Unknown color model!\n");
787 D3DRENDERSTATETYPE rs;
788 switch (dwLightStateType) {
790 case D3DLIGHTSTATE_AMBIENT: /* 2 */
791 rs = D3DRENDERSTATE_AMBIENT;
793 case D3DLIGHTSTATE_FOGMODE: /* 4 */
794 rs = D3DRENDERSTATE_FOGVERTEXMODE;
796 case D3DLIGHTSTATE_FOGSTART: /* 5 */
797 rs = D3DRENDERSTATE_FOGSTART;
799 case D3DLIGHTSTATE_FOGEND: /* 6 */
800 rs = D3DRENDERSTATE_FOGEND;
802 case D3DLIGHTSTATE_FOGDENSITY: /* 7 */
803 rs = D3DRENDERSTATE_FOGDENSITY;
805 case D3DLIGHTSTATE_COLORVERTEX: /* 8 */
806 rs = D3DRENDERSTATE_COLORVERTEX;
812 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This, IDirect3DDevice7),
819 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt)
822 case D3DPT_POINTLIST:
823 TRACE("Start POINTS\n");
828 TRACE("Start LINES\n");
832 case D3DPT_LINESTRIP:
833 TRACE("Start LINE_STRIP\n");
834 glBegin(GL_LINE_STRIP);
837 case D3DPT_TRIANGLELIST:
838 TRACE("Start TRIANGLES\n");
839 glBegin(GL_TRIANGLES);
842 case D3DPT_TRIANGLESTRIP:
843 TRACE("Start TRIANGLE_STRIP\n");
844 glBegin(GL_TRIANGLE_STRIP);
847 case D3DPT_TRIANGLEFAN:
848 TRACE("Start TRIANGLE_FAN\n");
849 glBegin(GL_TRIANGLE_FAN);
853 FIXME("Unhandled primitive %08x\n", d3dpt);
858 /* This function calculate the Z coordinate from Zproj */
859 static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
862 /* Assume that X = Y = 0 and W = 1 */
863 a = This->proj_mat->_33;
864 b = This->proj_mat->_34;
865 c = This->proj_mat->_43;
866 d = This->proj_mat->_44;
867 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
868 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
869 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
871 return (d*Zproj - c) / (a - b*Zproj);
874 static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
877 TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
879 for (i = 0; i < 3; i++) {
880 BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
882 for (elt = 0; elt < 0x10000; elt++) {
883 /* We apply the fog transformation and cache the result */
884 DWORD fog_intensity = elt & 0xFF;
885 DWORD vertex_color = (elt >> 8) & 0xFF;
886 fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
891 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
892 BOOLEAN vertex_transformed,
893 BOOLEAN vertex_lit) {
894 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
896 /* Puts GL in the correct lighting / transformation mode */
897 if ((vertex_transformed == FALSE) &&
898 (glThis->transform_state != GL_TRANSFORM_NORMAL)) {
899 /* Need to put the correct transformation again if we go from Transformed
900 vertices to non-transformed ones.
902 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
903 This->world_mat, This->view_mat, This->proj_mat);
904 glThis->transform_state = GL_TRANSFORM_NORMAL;
906 } else if ((vertex_transformed == TRUE) &&
907 (glThis->transform_state != GL_TRANSFORM_ORTHO)) {
908 /* Set our orthographic projection */
909 if (glThis->transform_state != GL_TRANSFORM_ORTHO) {
910 glThis->transform_state = GL_TRANSFORM_ORTHO;
911 d3ddevice_set_ortho(This);
915 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
916 if no fogging state change occurred */
917 if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
918 if (vertex_transformed == TRUE) {
919 if (glThis->fogging != 0) {
923 /* Now check if our fog_table still corresponds to the current vertex color.
924 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
925 if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
926 (glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
927 (glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
928 /* We need to rebuild our fog table.... */
929 build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
932 if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
933 switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
934 case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
935 case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
936 case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); break;
938 if (vertex_lit == FALSE) {
939 glFogf(GL_FOG_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
940 glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]);
942 /* Special case of 'pixel fog' */
943 glFogf(GL_FOG_START, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]));
944 glFogf(GL_FOG_END, ZfromZproj(This, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]));
946 if (glThis->fogging == 0) {
951 if (glThis->fogging != 0) {
958 if (glThis->fogging != 0) {
964 /* Handle the 'no-normal' case */
965 if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE)) {
966 if (glThis->lighting == 0) {
967 glEnable(GL_LIGHTING);
968 glThis->lighting = 1;
971 if (glThis->lighting != 0) {
972 glDisable(GL_LIGHTING);
973 glThis->lighting = 0;
977 /* Handle the code for pre-vertex material properties */
978 if (vertex_transformed == FALSE) {
979 if ((This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
980 (This->state_block.render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
981 if ((This->state_block.render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
982 (This->state_block.render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
983 (This->state_block.render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] != D3DMCS_MATERIAL) ||
984 (This->state_block.render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] != D3DMCS_MATERIAL)) {
985 glEnable(GL_COLOR_MATERIAL);
992 inline static void draw_primitive(IDirect3DDeviceImpl *This, DWORD maxvert, WORD *index,
993 D3DVERTEXTYPE d3dvt, D3DPRIMITIVETYPE d3dpt, void *lpvertex)
995 D3DDRAWPRIMITIVESTRIDEDDATA strided;
999 strided.position.lpvData = &((D3DVERTEX *) lpvertex)->u1.x;
1000 strided.position.dwStride = sizeof(D3DVERTEX);
1001 strided.normal.lpvData = &((D3DVERTEX *) lpvertex)->u4.nx;
1002 strided.normal.dwStride = sizeof(D3DVERTEX);
1003 strided.textureCoords[0].lpvData = &((D3DVERTEX *) lpvertex)->u7.tu;
1004 strided.textureCoords[0].dwStride = sizeof(D3DVERTEX);
1005 draw_primitive_strided(This, d3dpt, D3DFVF_VERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1008 case D3DVT_LVERTEX: {
1009 strided.position.lpvData = &((D3DLVERTEX *) lpvertex)->u1.x;
1010 strided.position.dwStride = sizeof(D3DLVERTEX);
1011 strided.diffuse.lpvData = &((D3DLVERTEX *) lpvertex)->u4.color;
1012 strided.diffuse.dwStride = sizeof(D3DLVERTEX);
1013 strided.specular.lpvData = &((D3DLVERTEX *) lpvertex)->u5.specular;
1014 strided.specular.dwStride = sizeof(D3DLVERTEX);
1015 strided.textureCoords[0].lpvData = &((D3DLVERTEX *) lpvertex)->u6.tu;
1016 strided.textureCoords[0].dwStride = sizeof(D3DLVERTEX);
1017 draw_primitive_strided(This, d3dpt, D3DFVF_LVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1020 case D3DVT_TLVERTEX: {
1021 strided.position.lpvData = &((D3DTLVERTEX *) lpvertex)->u1.sx;
1022 strided.position.dwStride = sizeof(D3DTLVERTEX);
1023 strided.diffuse.lpvData = &((D3DTLVERTEX *) lpvertex)->u5.color;
1024 strided.diffuse.dwStride = sizeof(D3DTLVERTEX);
1025 strided.specular.lpvData = &((D3DTLVERTEX *) lpvertex)->u6.specular;
1026 strided.specular.dwStride = sizeof(D3DTLVERTEX);
1027 strided.textureCoords[0].lpvData = &((D3DTLVERTEX *) lpvertex)->u7.tu;
1028 strided.textureCoords[0].dwStride = sizeof(D3DTLVERTEX);
1029 draw_primitive_strided(This, d3dpt, D3DFVF_TLVERTEX, &strided, 0 /* Unused */, index, maxvert, 0 /* Unused */);
1033 FIXME("Unhandled vertex type %08x\n", d3dvt);
1039 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface,
1040 D3DPRIMITIVETYPE d3dptPrimitiveType,
1041 D3DVERTEXTYPE d3dvtVertexType,
1043 DWORD dwVertexCount,
1046 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1048 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1049 if (TRACE_ON(ddraw)) {
1050 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1053 draw_primitive(This, dwVertexCount, NULL, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1059 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface,
1060 D3DPRIMITIVETYPE d3dptPrimitiveType,
1061 D3DVERTEXTYPE d3dvtVertexType,
1063 DWORD dwVertexCount,
1068 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice2, iface);
1069 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1070 if (TRACE_ON(ddraw)) {
1071 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1074 draw_primitive(This, dwIndexCount, dwIndices, d3dvtVertexType, d3dptPrimitiveType, lpvVertices);
1080 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface,
1081 LPD3DEXECUTEBUFFERDESC lpDesc,
1082 LPDIRECT3DEXECUTEBUFFER* lplpDirect3DExecuteBuffer,
1083 IUnknown* pUnkOuter)
1085 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice, iface);
1086 IDirect3DExecuteBufferImpl *ret;
1089 TRACE("(%p/%p)->(%p,%p,%p)\n", This, iface, lpDesc, lplpDirect3DExecuteBuffer, pUnkOuter);
1091 ret_value = d3dexecutebuffer_create(&ret, This->d3d, This, lpDesc);
1092 *lplpDirect3DExecuteBuffer = ICOM_INTERFACE(ret, IDirect3DExecuteBuffer);
1094 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer);
1099 /* These are the various handler used in the generic path */
1100 inline static void handle_xyz(D3DVALUE *coords) {
1101 glVertex3fv(coords);
1103 inline static void handle_xyzrhw(D3DVALUE *coords) {
1104 if (coords[3] < 1e-8)
1105 glVertex3fv(coords);
1107 GLfloat w = 1.0 / coords[3];
1109 glVertex4f(coords[0] * w,
1115 inline static void handle_normal(D3DVALUE *coords) {
1116 glNormal3fv(coords);
1119 inline static void handle_diffuse_base(STATEBLOCK *sb, DWORD *color) {
1120 if ((sb->render_state[D3DRENDERSTATE_ALPHATESTENABLE - 1] == TRUE) ||
1121 (sb->render_state[D3DRENDERSTATE_ALPHABLENDENABLE - 1] == TRUE)) {
1122 glColor4ub((*color >> 16) & 0xFF,
1123 (*color >> 8) & 0xFF,
1124 (*color >> 0) & 0xFF,
1125 (*color >> 24) & 0xFF);
1127 glColor3ub((*color >> 16) & 0xFF,
1128 (*color >> 8) & 0xFF,
1129 (*color >> 0) & 0xFF);
1133 inline static void handle_specular_base(STATEBLOCK *sb, DWORD *color) {
1134 glColor4ub((*color >> 16) & 0xFF,
1135 (*color >> 8) & 0xFF,
1136 (*color >> 0) & 0xFF,
1137 (*color >> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1140 inline static void handle_diffuse(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1141 if ((lighted == FALSE) &&
1142 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1143 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1144 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1145 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1146 handle_diffuse_base(sb, color);
1148 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1149 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1150 handle_diffuse_base(sb, color);
1152 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR1) &&
1153 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1154 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1155 handle_diffuse_base(sb, color);
1157 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR1) {
1158 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1159 handle_diffuse_base(sb, color);
1162 handle_diffuse_base(sb, color);
1166 inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted) {
1167 if ((lighted == FALSE) &&
1168 (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) &&
1169 (sb->render_state[D3DRENDERSTATE_COLORVERTEX - 1] == TRUE)) {
1170 if (sb->render_state[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1171 glColorMaterial(GL_FRONT_AND_BACK, GL_DIFFUSE);
1172 handle_specular_base(sb, color);
1174 if (sb->render_state[D3DRENDERSTATE_AMBIENTMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1175 glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT);
1176 handle_specular_base(sb, color);
1178 if ((sb->render_state[D3DRENDERSTATE_SPECULARMATERIALSOURCE - 1] == D3DMCS_COLOR2) &&
1179 (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE)) {
1180 glColorMaterial(GL_FRONT_AND_BACK, GL_SPECULAR);
1181 handle_specular_base(sb, color);
1183 if (sb->render_state[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE - 1] == D3DMCS_COLOR2) {
1184 glColorMaterial(GL_FRONT_AND_BACK, GL_EMISSION);
1185 handle_specular_base(sb, color);
1188 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1191 inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
1192 if (lighted == TRUE) {
1193 DWORD color = *color_d;
1194 if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
1195 /* Special case where the specular value is used to do fogging */
1196 BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1197 color &= 0xFF000000; /* Only keep the alpha component */
1198 color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
1199 color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
1200 color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
1202 if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
1203 /* Standard specular value in transformed mode. TODO */
1205 handle_diffuse_base(sb, &color);
1207 if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
1208 handle_diffuse(sb, color_d, FALSE);
1209 handle_specular(sb, color_s, FALSE);
1211 /* In that case, only put the diffuse color... */
1212 handle_diffuse_base(sb, color_d);
1217 inline static void handle_texture(D3DVALUE *coords) {
1218 glTexCoord2fv(coords);
1220 inline static void handle_textures(D3DVALUE *coords, int tex_stage) {
1221 if (GL_extensions.glMultiTexCoord2fv) {
1222 GL_extensions.glMultiTexCoord2fv(GL_TEXTURE0_WINE + tex_stage, coords);
1224 if (tex_stage == 0) glTexCoord2fv(coords);
1228 static void draw_primitive_strided(IDirect3DDeviceImpl *This,
1229 D3DPRIMITIVETYPE d3dptPrimitiveType,
1230 DWORD d3dvtVertexType,
1231 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1232 DWORD dwVertexCount,
1237 BOOLEAN vertex_lighted = FALSE;
1238 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
1239 int num_active_stages = 0;
1241 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1242 if (TRACE_ON(ddraw)) {
1243 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
1246 /* This is to prevent 'thread contention' between a thread locking the device and another
1247 doing 3D display on it... */
1248 EnterCriticalSection(&(This->crit));
1251 if (glThis->state[WINE_GL_BUFFER_BACK] == SURFACE_MEMORY_DIRTY) {
1252 This->flush_to_framebuffer(This, &(glThis->lock_rect[WINE_GL_BUFFER_BACK]), glThis->lock_surf[WINE_GL_BUFFER_BACK]);
1255 glThis->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
1257 /* Just a hack for now.. Will have to find better algorithm :-/ */
1258 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ) {
1259 vertex_lighted = TRUE;
1261 if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
1264 /* Compute the number of active texture stages and set the various texture parameters */
1265 num_active_stages = draw_primitive_handle_textures(This);
1267 /* And restore to handle '0' in the case we use glTexCorrd calls */
1268 if (glThis->current_active_tex_unit != GL_TEXTURE0_WINE) {
1269 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
1270 glThis->current_active_tex_unit = GL_TEXTURE0_WINE;
1274 draw_primitive_handle_GL_state(This,
1275 (d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
1277 draw_primitive_start_GL(d3dptPrimitiveType);
1279 /* Some fast paths first before the generic case.... */
1280 if ((d3dvtVertexType == D3DFVF_VERTEX) && (num_active_stages <= 1)) {
1283 for (index = 0; index < dwIndexCount; index++) {
1284 int i = (dwIndices == NULL) ? index : dwIndices[index];
1286 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1287 D3DVALUE *tex_coord =
1288 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1289 D3DVALUE *position =
1290 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1292 handle_normal(normal);
1293 handle_texture(tex_coord);
1294 handle_xyz(position);
1296 TRACE_(ddraw_geom)(" %f %f %f / %f %f %f (%f %f)\n",
1297 position[0], position[1], position[2],
1298 normal[0], normal[1], normal[2],
1299 tex_coord[0], tex_coord[1]);
1301 } else if ((d3dvtVertexType == D3DFVF_TLVERTEX) && (num_active_stages <= 1)) {
1304 for (index = 0; index < dwIndexCount; index++) {
1305 int i = (dwIndices == NULL) ? index : dwIndices[index];
1307 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1309 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1310 D3DVALUE *tex_coord =
1311 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[0].lpvData) + i * lpD3DDrawPrimStrideData->textureCoords[0].dwStride);
1312 D3DVALUE *position =
1313 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1315 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
1316 handle_texture(tex_coord);
1317 handle_xyzrhw(position);
1319 TRACE_(ddraw_geom)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1320 position[0], position[1], position[2], position[3],
1321 (*color_d >> 16) & 0xFF,
1322 (*color_d >> 8) & 0xFF,
1323 (*color_d >> 0) & 0xFF,
1324 (*color_d >> 24) & 0xFF,
1325 (*color_s >> 16) & 0xFF,
1326 (*color_s >> 8) & 0xFF,
1327 (*color_s >> 0) & 0xFF,
1328 (*color_s >> 24) & 0xFF,
1329 tex_coord[0], tex_coord[1]);
1331 } else if (((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) ||
1332 ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW)) {
1333 /* This is the 'slow path' but that should support all possible vertex formats out there...
1334 Note that people should write a fast path for all vertex formats out there...
1337 int num_tex_index = ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT);
1338 static const D3DVALUE no_index[] = { 0.0, 0.0, 0.0, 0.0 };
1340 for (index = 0; index < dwIndexCount; index++) {
1341 int i = (dwIndices == NULL) ? index : dwIndices[index];
1344 if (d3dvtVertexType & D3DFVF_NORMAL) {
1346 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1347 handle_normal(normal);
1349 if ((d3dvtVertexType & (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) == (D3DFVF_DIFFUSE|D3DFVF_SPECULAR)) {
1351 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1353 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1354 handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
1356 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1358 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1359 handle_specular(&(This->state_block), color_s, vertex_lighted);
1360 } else if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1362 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1363 handle_diffuse(&(This->state_block), color_d, vertex_lighted);
1367 for (tex_stage = 0; tex_stage < num_active_stages; tex_stage++) {
1368 int tex_index = This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXCOORDINDEX - 1] & 0x0000FFFF;
1369 if (tex_index >= num_tex_index) {
1370 handle_textures((D3DVALUE *) no_index, tex_stage);
1372 D3DVALUE *tex_coord =
1373 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1374 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1375 handle_textures(tex_coord, tex_stage);
1379 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1380 D3DVALUE *position =
1381 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1382 handle_xyz(position);
1383 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1384 D3DVALUE *position =
1385 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1386 handle_xyzrhw(position);
1389 if (TRACE_ON(ddraw_geom)) {
1392 if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) {
1393 D3DVALUE *position =
1394 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1395 TRACE_(ddraw_geom)(" %f %f %f", position[0], position[1], position[2]);
1396 } else if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZRHW) {
1397 D3DVALUE *position =
1398 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
1399 TRACE_(ddraw_geom)(" %f %f %f %f", position[0], position[1], position[2], position[3]);
1401 if (d3dvtVertexType & D3DFVF_NORMAL) {
1403 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->normal.lpvData) + i * lpD3DDrawPrimStrideData->normal.dwStride);
1404 TRACE_(ddraw_geom)(" / %f %f %f", normal[0], normal[1], normal[2]);
1406 if (d3dvtVertexType & D3DFVF_DIFFUSE) {
1408 (DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
1409 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1410 (*color_d >> 16) & 0xFF,
1411 (*color_d >> 8) & 0xFF,
1412 (*color_d >> 0) & 0xFF,
1413 (*color_d >> 24) & 0xFF);
1415 if (d3dvtVertexType & D3DFVF_SPECULAR) {
1417 (DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
1418 TRACE_(ddraw_geom)(" / %02lx %02lx %02lx %02lx",
1419 (*color_s >> 16) & 0xFF,
1420 (*color_s >> 8) & 0xFF,
1421 (*color_s >> 0) & 0xFF,
1422 (*color_s >> 24) & 0xFF);
1424 for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) {
1425 D3DVALUE *tex_coord =
1426 (D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->textureCoords[tex_index].lpvData) +
1427 i * lpD3DDrawPrimStrideData->textureCoords[tex_index].dwStride);
1428 TRACE_(ddraw_geom)(" / %f %f", tex_coord[0], tex_coord[1]);
1430 TRACE_(ddraw_geom)("\n");
1434 ERR(" matrix weighting not handled yet....\n");
1439 /* Whatever the case, disable the color material stuff */
1440 glDisable(GL_COLOR_MATERIAL);
1445 LeaveCriticalSection(&(This->crit));
1449 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface,
1450 D3DPRIMITIVETYPE d3dptPrimitiveType,
1451 DWORD d3dvtVertexType,
1453 DWORD dwVertexCount,
1456 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1457 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1459 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwFlags);
1460 if (TRACE_ON(ddraw)) {
1461 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1464 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1465 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, NULL, dwVertexCount, dwFlags);
1471 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface,
1472 D3DPRIMITIVETYPE d3dptPrimitiveType,
1473 DWORD d3dvtVertexType,
1475 DWORD dwVertexCount,
1480 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1481 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1483 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, d3dvtVertexType, lpvVertices, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1484 if (TRACE_ON(ddraw)) {
1485 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1488 convert_FVF_to_strided_data(d3dvtVertexType, lpvVertices, &strided, 0);
1489 draw_primitive_strided(This, d3dptPrimitiveType, d3dvtVertexType, &strided, dwVertexCount, dwIndices, dwIndexCount, dwFlags);
1495 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1496 D3DPRIMITIVETYPE d3dptPrimitiveType,
1498 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1499 DWORD dwVertexCount,
1502 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1504 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, dwFlags);
1505 if (TRACE_ON(ddraw)) {
1506 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1508 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, NULL, dwVertexCount, dwFlags);
1514 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface,
1515 D3DPRIMITIVETYPE d3dptPrimitiveType,
1517 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData,
1518 DWORD dwVertexCount,
1523 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1525 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1526 if (TRACE_ON(ddraw)) {
1527 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1530 draw_primitive_strided(This, d3dptPrimitiveType, dwVertexType, lpD3DDrawPrimStrideData, dwVertexCount, lpIndex, dwIndexCount, dwFlags);
1536 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1537 D3DPRIMITIVETYPE d3dptPrimitiveType,
1538 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1539 DWORD dwStartVertex,
1540 DWORD dwNumVertices,
1543 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1544 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1545 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1547 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, dwFlags);
1548 if (TRACE_ON(ddraw)) {
1549 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1552 if (vb_impl->processed == TRUE) {
1553 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1554 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1556 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1557 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1558 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1560 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1561 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1564 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1565 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, NULL, dwNumVertices, dwFlags);
1572 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
1573 D3DPRIMITIVETYPE d3dptPrimitiveType,
1574 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf,
1575 DWORD dwStartVertex,
1576 DWORD dwNumVertices,
1581 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1582 IDirect3DVertexBufferImpl *vb_impl = ICOM_OBJECT(IDirect3DVertexBufferImpl, IDirect3DVertexBuffer7, lpD3DVertexBuf);
1583 D3DDRAWPRIMITIVESTRIDEDDATA strided;
1585 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This, iface, d3dptPrimitiveType, lpD3DVertexBuf, dwStartVertex, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1586 if (TRACE_ON(ddraw)) {
1587 TRACE(" - flags : "); dump_DPFLAGS(dwFlags);
1590 if (vb_impl->processed == TRUE) {
1591 IDirect3DVertexBufferGLImpl *vb_glimp = (IDirect3DVertexBufferGLImpl *) vb_impl;
1592 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1594 glThis->transform_state = GL_TRANSFORM_VERTEXBUFFER;
1595 This->set_matrices(This, VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED,
1596 &(vb_glimp->world_mat), &(vb_glimp->view_mat), &(vb_glimp->proj_mat));
1598 convert_FVF_to_strided_data(vb_glimp->dwVertexTypeDesc, vb_glimp->vertices, &strided, dwStartVertex);
1599 draw_primitive_strided(This, d3dptPrimitiveType, vb_glimp->dwVertexTypeDesc, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1602 convert_FVF_to_strided_data(vb_impl->desc.dwFVF, vb_impl->vertices, &strided, dwStartVertex);
1603 draw_primitive_strided(This, d3dptPrimitiveType, vb_impl->desc.dwFVF, &strided, dwNumVertices, lpwIndices, dwIndexCount, dwFlags);
1609 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1611 handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
1613 BOOLEAN is_complement = FALSE;
1614 BOOLEAN is_alpha_replicate = FALSE;
1615 BOOLEAN handled = TRUE;
1617 BOOLEAN is_color = ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2));
1621 if (d3dTexStageStateType == D3DTSS_COLORARG1) num = 0;
1622 else if (d3dTexStageStateType == D3DTSS_COLORARG2) num = 1;
1627 if (tex_op == D3DTOP_SELECTARG2) {
1631 if (d3dTexStageStateType == D3DTSS_ALPHAARG1) num = 0;
1632 else if (d3dTexStageStateType == D3DTSS_ALPHAARG2) num = 1;
1637 if (tex_op == D3DTOP_SELECTARG2) {
1642 if (dwState & D3DTA_COMPLEMENT) {
1643 is_complement = TRUE;
1645 if (dwState & D3DTA_ALPHAREPLICATE) {
1646 is_alpha_replicate = TRUE;
1648 dwState &= D3DTA_SELECTMASK;
1649 if ((dwStage == 0) && (dwState == D3DTA_CURRENT)) {
1650 dwState = D3DTA_DIFFUSE;
1654 case D3DTA_CURRENT: src = GL_PREVIOUS_EXT; break;
1655 case D3DTA_DIFFUSE: src = GL_PRIMARY_COLOR_EXT; break;
1656 case D3DTA_TEXTURE: src = GL_TEXTURE; break;
1657 case D3DTA_TFACTOR: {
1658 /* Get the constant value from the current rendering state */
1660 DWORD col = This->state_block.render_state[D3DRENDERSTATE_TEXTUREFACTOR - 1];
1662 color[0] = ((col >> 16) & 0xFF) / 255.0f;
1663 color[1] = ((col >> 8) & 0xFF) / 255.0f;
1664 color[2] = ((col >> 0) & 0xFF) / 255.0f;
1665 color[3] = ((col >> 24) & 0xFF) / 255.0f;
1666 glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);
1668 src = GL_CONSTANT_EXT;
1670 default: src = GL_TEXTURE; handled = FALSE; break;
1674 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_EXT + num, src);
1675 if (is_alpha_replicate) {
1676 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1678 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_EXT + num, is_complement ? GL_ONE_MINUS_SRC_COLOR : GL_SRC_COLOR);
1681 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_EXT + num, src);
1682 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_EXT + num, is_complement ? GL_ONE_MINUS_SRC_ALPHA : GL_SRC_ALPHA);
1689 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
1691 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType,
1694 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
1695 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
1700 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This, iface, dwStage, d3dTexStageStateType, dwState);
1702 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
1703 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
1707 unit = GL_TEXTURE0_WINE + dwStage;
1708 if (unit != glThis->current_active_tex_unit) {
1709 GL_extensions.glActiveTexture(unit);
1710 glThis->current_active_tex_unit = unit;
1713 switch (d3dTexStageStateType) {
1714 #define GEN_CASE(a) case a: type = #a; break
1715 GEN_CASE(D3DTSS_COLOROP);
1716 GEN_CASE(D3DTSS_COLORARG1);
1717 GEN_CASE(D3DTSS_COLORARG2);
1718 GEN_CASE(D3DTSS_ALPHAOP);
1719 GEN_CASE(D3DTSS_ALPHAARG1);
1720 GEN_CASE(D3DTSS_ALPHAARG2);
1721 GEN_CASE(D3DTSS_BUMPENVMAT00);
1722 GEN_CASE(D3DTSS_BUMPENVMAT01);
1723 GEN_CASE(D3DTSS_BUMPENVMAT10);
1724 GEN_CASE(D3DTSS_BUMPENVMAT11);
1725 GEN_CASE(D3DTSS_TEXCOORDINDEX);
1726 GEN_CASE(D3DTSS_ADDRESS);
1727 GEN_CASE(D3DTSS_ADDRESSU);
1728 GEN_CASE(D3DTSS_ADDRESSV);
1729 GEN_CASE(D3DTSS_BORDERCOLOR);
1730 GEN_CASE(D3DTSS_MAGFILTER);
1731 GEN_CASE(D3DTSS_MINFILTER);
1732 GEN_CASE(D3DTSS_MIPFILTER);
1733 GEN_CASE(D3DTSS_MIPMAPLODBIAS);
1734 GEN_CASE(D3DTSS_MAXMIPLEVEL);
1735 GEN_CASE(D3DTSS_MAXANISOTROPY);
1736 GEN_CASE(D3DTSS_BUMPENVLSCALE);
1737 GEN_CASE(D3DTSS_BUMPENVLOFFSET);
1738 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS);
1740 default: type = "UNKNOWN";
1743 /* Store the values in the state array */
1744 prev_state = This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1];
1745 This->state_block.texture_stage_state[dwStage][d3dTexStageStateType - 1] = dwState;
1746 /* Some special cases when one state modifies more than one... */
1747 if (d3dTexStageStateType == D3DTSS_ADDRESS) {
1748 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1] = dwState;
1749 This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1] = dwState;
1754 switch (d3dTexStageStateType) {
1755 case D3DTSS_MINFILTER:
1756 case D3DTSS_MIPFILTER:
1757 if (TRACE_ON(ddraw)) {
1758 if (d3dTexStageStateType == D3DTSS_MINFILTER) {
1759 switch ((D3DTEXTUREMINFILTER) dwState) {
1760 case D3DTFN_POINT: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1761 case D3DTFN_LINEAR: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1762 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState); break;
1765 switch ((D3DTEXTUREMIPFILTER) dwState) {
1766 case D3DTFP_NONE: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1767 case D3DTFP_POINT: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1768 case D3DTFP_LINEAR: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1769 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState); break;
1775 case D3DTSS_MAGFILTER:
1776 if (TRACE_ON(ddraw)) {
1777 switch ((D3DTEXTUREMAGFILTER) dwState) {
1778 case D3DTFG_POINT: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1779 case D3DTFG_LINEAR: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1780 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
1785 case D3DTSS_ADDRESS:
1786 case D3DTSS_ADDRESSU:
1787 case D3DTSS_ADDRESSV: {
1788 switch ((D3DTEXTUREADDRESS) dwState) {
1789 case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
1790 case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
1791 case D3DTADDRESS_BORDER: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type); break;
1792 case D3DTADDRESS_MIRROR:
1793 if (GL_extensions.mirrored_repeat == TRUE) {
1794 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type);
1796 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type);
1799 default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
1803 case D3DTSS_ALPHAOP:
1804 case D3DTSS_COLOROP: {
1806 GLenum parm = (d3dTexStageStateType == D3DTSS_ALPHAOP) ? GL_COMBINE_ALPHA_EXT : GL_COMBINE_RGB_EXT;
1811 #define GEN_CASE(a) case a: value = #a; break
1812 GEN_CASE(D3DTOP_DISABLE);
1813 GEN_CASE(D3DTOP_SELECTARG1);
1814 GEN_CASE(D3DTOP_SELECTARG2);
1815 GEN_CASE(D3DTOP_MODULATE);
1816 GEN_CASE(D3DTOP_MODULATE2X);
1817 GEN_CASE(D3DTOP_MODULATE4X);
1818 GEN_CASE(D3DTOP_ADD);
1819 GEN_CASE(D3DTOP_ADDSIGNED);
1820 GEN_CASE(D3DTOP_ADDSIGNED2X);
1821 GEN_CASE(D3DTOP_SUBTRACT);
1822 GEN_CASE(D3DTOP_ADDSMOOTH);
1823 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA);
1824 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA);
1825 GEN_CASE(D3DTOP_BLENDFACTORALPHA);
1826 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM);
1827 GEN_CASE(D3DTOP_BLENDCURRENTALPHA);
1828 GEN_CASE(D3DTOP_PREMODULATE);
1829 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR);
1830 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA);
1831 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR);
1832 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA);
1833 GEN_CASE(D3DTOP_BUMPENVMAP);
1834 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE);
1835 GEN_CASE(D3DTOP_DOTPRODUCT3);
1836 GEN_CASE(D3DTOP_FORCE_DWORD);
1838 default: value = "UNKNOWN";
1841 if ((d3dTexStageStateType == D3DTSS_COLOROP) && (dwState == D3DTOP_DISABLE)) {
1842 glDisable(GL_TEXTURE_2D);
1843 TRACE(" disabling 2D texturing.\n");
1845 /* Re-enable texturing */
1846 if (This->current_texture[0] != NULL) {
1847 glEnable(GL_TEXTURE_2D);
1848 TRACE(" enabling 2D texturing.\n");
1851 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1852 if (dwState != D3DTOP_DISABLE) {
1853 if (glThis->current_tex_env != GL_COMBINE_EXT) {
1854 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);
1855 glThis->current_tex_env = GL_COMBINE_EXT;
1859 /* Now set up the operand correctly */
1861 case D3DTOP_DISABLE:
1862 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1863 and it works, so ignore this op */
1864 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1867 case D3DTOP_SELECTARG1:
1868 case D3DTOP_SELECTARG2:
1869 glTexEnvi(GL_TEXTURE_ENV, parm, GL_REPLACE);
1872 case D3DTOP_MODULATE4X:
1873 scale = scale * 2; /* Drop through */
1874 case D3DTOP_MODULATE2X:
1875 scale = scale * 2; /* Drop through */
1876 case D3DTOP_MODULATE:
1877 glTexEnvi(GL_TEXTURE_ENV, parm, GL_MODULATE);
1881 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD);
1884 case D3DTOP_ADDSIGNED2X:
1885 scale = scale * 2; /* Drop through */
1886 case D3DTOP_ADDSIGNED:
1887 glTexEnvi(GL_TEXTURE_ENV, parm, GL_ADD_SIGNED_EXT);
1890 /* For the four blending modes, use the Arg2 parameter */
1891 case D3DTOP_BLENDDIFFUSEALPHA:
1892 case D3DTOP_BLENDTEXTUREALPHA:
1893 case D3DTOP_BLENDFACTORALPHA:
1894 case D3DTOP_BLENDCURRENTALPHA: {
1895 GLenum src = GL_PRIMARY_COLOR_EXT; /* Just to prevent a compiler warning.. */
1898 case D3DTOP_BLENDDIFFUSEALPHA: src = GL_PRIMARY_COLOR_EXT;
1899 case D3DTOP_BLENDTEXTUREALPHA: src = GL_TEXTURE;
1900 case D3DTOP_BLENDFACTORALPHA: src = GL_CONSTANT_EXT;
1901 case D3DTOP_BLENDCURRENTALPHA: src = GL_PREVIOUS_EXT;
1904 glTexEnvi(GL_TEXTURE_ENV, parm, GL_INTERPOLATE_EXT);
1905 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_EXT, src);
1906 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA);
1907 glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA_EXT, src);
1908 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA);
1917 if (((prev_state == D3DTOP_SELECTARG2) && (dwState != D3DTOP_SELECTARG2)) ||
1918 ((dwState == D3DTOP_SELECTARG2) && (prev_state != D3DTOP_SELECTARG2))) {
1919 /* Switch the arguments if needed... */
1920 if (d3dTexStageStateType == D3DTSS_COLOROP) {
1921 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG1,
1922 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG1 - 1],
1924 handle_color_alpha_args(This, dwStage, D3DTSS_COLORARG2,
1925 This->state_block.texture_stage_state[dwStage][D3DTSS_COLORARG2 - 1],
1928 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG1,
1929 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG1 - 1],
1931 handle_color_alpha_args(This, dwStage, D3DTSS_ALPHAARG2,
1932 This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAARG2 - 1],
1938 if (d3dTexStageStateType == D3DTSS_ALPHAOP) {
1939 glTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, scale);
1941 glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_EXT, scale);
1943 TRACE(" Stage type is : %s => %s\n", type, value);
1945 FIXME(" Unhandled stage type is : %s => %s\n", type, value);
1949 case D3DTSS_COLORARG1:
1950 case D3DTSS_COLORARG2:
1951 case D3DTSS_ALPHAARG1:
1952 case D3DTSS_ALPHAARG2: {
1953 const char *value, *value_comp = "", *value_alpha = "";
1955 D3DTEXTUREOP tex_op;
1957 switch (dwState & D3DTA_SELECTMASK) {
1958 #define GEN_CASE(a) case a: value = #a; break
1959 GEN_CASE(D3DTA_DIFFUSE);
1960 GEN_CASE(D3DTA_CURRENT);
1961 GEN_CASE(D3DTA_TEXTURE);
1962 GEN_CASE(D3DTA_TFACTOR);
1963 GEN_CASE(D3DTA_SPECULAR);
1965 default: value = "UNKNOWN";
1967 if (dwState & D3DTA_COMPLEMENT) {
1968 value_comp = " | D3DTA_COMPLEMENT";
1970 if (dwState & D3DTA_ALPHAREPLICATE) {
1971 value_alpha = " | D3DTA_ALPHAREPLICATE";
1974 if ((d3dTexStageStateType == D3DTSS_COLORARG1) || (d3dTexStageStateType == D3DTSS_COLORARG2)) {
1975 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1];
1977 tex_op = This->state_block.texture_stage_state[dwStage][D3DTSS_ALPHAOP - 1];
1980 handled = handle_color_alpha_args(This, dwStage, d3dTexStageStateType, dwState, tex_op);
1983 TRACE(" Stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1985 FIXME(" Unhandled stage type : %s => %s%s%s\n", type, value, value_comp, value_alpha);
1989 case D3DTSS_MIPMAPLODBIAS: {
1990 D3DVALUE value = *((D3DVALUE *) &dwState);
1991 BOOLEAN handled = TRUE;
1993 if ((value != 0.0) && (GL_extensions.mipmap_lodbias == FALSE))
1997 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
1998 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE, GL_TEXTURE_LOD_BIAS_WINE, value);
2000 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value);
2004 case D3DTSS_MAXMIPLEVEL:
2005 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
2008 case D3DTSS_BORDERCOLOR:
2009 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2010 ((dwState >> 16) & 0xFF),
2011 ((dwState >> 8) & 0xFF),
2012 ((dwState >> 0) & 0xFF),
2013 ((dwState >> 24) & 0xFF));
2016 case D3DTSS_TEXCOORDINDEX: {
2017 BOOLEAN handled = TRUE;
2020 switch (dwState & 0xFFFF0000) {
2021 #define GEN_CASE(a) case a: value = #a; break
2022 GEN_CASE(D3DTSS_TCI_PASSTHRU);
2023 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL);
2024 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION);
2025 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
2027 default: value = "UNKNOWN";
2029 if ((dwState & 0xFFFF0000) != D3DTSS_TCI_PASSTHRU)
2033 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2035 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState & 0x0000FFFF, value);
2039 case D3DTSS_TEXTURETRANSFORMFLAGS: {
2040 const char *projected = "", *value;
2041 BOOLEAN handled = TRUE;
2042 switch (dwState & 0xFF) {
2043 #define GEN_CASE(a) case a: value = #a; break
2044 GEN_CASE(D3DTTFF_DISABLE);
2045 GEN_CASE(D3DTTFF_COUNT1);
2046 GEN_CASE(D3DTTFF_COUNT2);
2047 GEN_CASE(D3DTTFF_COUNT3);
2048 GEN_CASE(D3DTTFF_COUNT4);
2050 default: value = "UNKNOWN";
2052 if (dwState & D3DTTFF_PROJECTED) {
2053 projected = " | D3DTTFF_PROJECTED";
2057 if ((dwState & 0xFF) != D3DTTFF_DISABLE) {
2058 This->matrices_updated(This, TEXMAT0_CHANGED << dwStage);
2061 if (handled == TRUE) {
2062 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2064 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value, projected);
2069 FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState);
2079 draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
2081 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2084 for (stage = 0; stage < MAX_TEXTURES; stage++) {
2085 IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
2088 /* First check if we need to bind any other texture for this stage */
2089 if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
2090 if (This->current_texture[stage] == NULL) {
2091 TRACE(" disabling 2D texturing for stage %ld.\n", stage);
2093 unit = GL_TEXTURE0_WINE + stage;
2094 if (unit != glThis->current_active_tex_unit) {
2095 GL_extensions.glActiveTexture(unit);
2096 glThis->current_active_tex_unit = unit;
2098 glBindTexture(GL_TEXTURE_2D, 0);
2101 glDisable(GL_TEXTURE_2D);
2104 GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
2106 unit = GL_TEXTURE0_WINE + stage;
2107 if (unit != glThis->current_active_tex_unit) {
2108 GL_extensions.glActiveTexture(unit);
2109 glThis->current_active_tex_unit = unit;
2112 if (glThis->current_bound_texture[stage] == NULL) {
2113 if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
2114 TRACE(" enabling 2D texturing and");
2115 glEnable(GL_TEXTURE_2D);
2118 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
2119 glBindTexture(GL_TEXTURE_2D, tex_name);
2122 glThis->current_bound_texture[stage] = This->current_texture[stage];
2124 if (glThis->current_bound_texture[stage] == NULL) {
2125 TRACE(" displaying without texturing activated for stage %ld.\n", stage);
2127 TRACE(" using already bound texture id %d for stage %ld.\n",
2128 ((IDirect3DTextureGLImpl *) (glThis->current_bound_texture[stage])->tex_private)->tex_name, stage);
2132 /* If no texure valid for this stage, go out of the loop */
2133 if (This->current_texture[stage] == NULL) break;
2135 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2136 This will also update the various texture parameters if needed.
2138 gltex_upload_texture(surf_ptr, This, stage);
2145 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
2147 LPDIRECTDRAWSURFACE7 lpTexture2)
2149 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2151 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwStage, lpTexture2);
2153 if (((GL_extensions.max_texture_units == 0) && (dwStage > 0)) ||
2154 ((GL_extensions.max_texture_units != 0) && (dwStage >= GL_extensions.max_texture_units))) {
2155 if (lpTexture2 != NULL) {
2156 WARN(" setting a texture to a non-supported texture stage !\n");
2161 if (This->current_texture[dwStage] != NULL) {
2162 IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
2165 if (lpTexture2 == NULL) {
2166 This->current_texture[dwStage] = NULL;
2168 IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
2169 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
2170 This->current_texture[dwStage] = tex_impl;
2177 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
2178 LPD3DDEVICEDESC7 lpD3DHELDevDesc)
2180 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2181 TRACE("(%p/%p)->(%p)\n", This, iface, lpD3DHELDevDesc);
2183 fill_opengl_caps_7(lpD3DHELDevDesc);
2185 TRACE(" returning caps : no dump function yet.\n");
2191 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
2192 LPD3DMATERIAL7 lpMat)
2194 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2195 TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
2197 if (TRACE_ON(ddraw)) {
2198 TRACE(" material is : \n");
2199 dump_D3DMATERIAL7(lpMat);
2202 This->current_material = *lpMat;
2205 glMaterialfv(GL_FRONT_AND_BACK,
2207 (float *) &(This->current_material.u.diffuse));
2208 glMaterialfv(GL_FRONT_AND_BACK,
2210 (float *) &(This->current_material.u1.ambient));
2211 glMaterialfv(GL_FRONT_AND_BACK,
2213 (float *) &(This->current_material.u2.specular));
2214 glMaterialfv(GL_FRONT_AND_BACK,
2216 (float *) &(This->current_material.u3.emissive));
2217 glMaterialf(GL_FRONT_AND_BACK,
2219 This->current_material.u4.power); /* Not sure about this... */
2227 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
2229 LPD3DLIGHT7 lpLight)
2231 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2232 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2233 TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
2235 if (TRACE_ON(ddraw)) {
2236 TRACE(" setting light : \n");
2237 dump_D3DLIGHT7(lpLight);
2240 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2241 This->set_lights |= 0x00000001 << dwLightIndex;
2242 This->light_parameters[dwLightIndex] = *lpLight;
2244 /* Some checks to print out nice warnings :-) */
2245 switch (lpLight->dltType) {
2246 case D3DLIGHT_DIRECTIONAL:
2247 case D3DLIGHT_POINT:
2248 /* These are handled properly... */
2252 if ((lpLight->dvTheta != 0.0) ||
2253 (lpLight->dvTheta != lpLight->dvPhi)) {
2254 ERR("dvTheta not fully supported yet !\n");
2259 ERR("Light type not handled yet : %08x !\n", lpLight->dltType);
2262 /* This will force the Light setting on next drawing of primitives */
2263 glThis->transform_state = GL_TRANSFORM_NONE;
2269 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
2273 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2274 TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
2276 if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
2280 if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
2281 /* Set the default parameters.. */
2282 TRACE(" setting default light parameters...\n");
2283 GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
2285 glEnable(GL_LIGHT0 + dwLightIndex);
2286 if ((This->active_lights & (0x00000001 << dwLightIndex)) == 0) {
2287 /* This light gets active... Need to update its parameters to GL before the next drawing */
2288 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2290 This->active_lights |= 0x00000001 << dwLightIndex;
2291 glThis->transform_state = GL_TRANSFORM_NONE;
2294 glDisable(GL_LIGHT0 + dwLightIndex);
2295 This->active_lights &= ~(0x00000001 << dwLightIndex);
2303 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface, DWORD dwIndex, CONST D3DVALUE* pPlaneEquation)
2305 ICOM_THIS(IDirect3DDeviceImpl,iface);
2306 IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
2308 TRACE("(%p)->(%ld,%p)\n", This, dwIndex, pPlaneEquation);
2310 if (dwIndex >= This->max_clipping_planes) {
2311 return DDERR_INVALIDPARAMS;
2314 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex, pPlaneEquation[0], pPlaneEquation[1], pPlaneEquation[2], pPlaneEquation[3] );
2316 memcpy(This->clipping_planes[dwIndex].plane, pPlaneEquation, sizeof(D3DVALUE[4]));
2318 /* This is to force the reset of the transformation matrices on the next drawing.
2319 * This is needed to use the correct matrices for the various clipping planes.
2321 glThis->transform_state = GL_TRANSFORM_NONE;
2327 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface,
2328 LPD3DVIEWPORT7 lpData)
2330 ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
2331 TRACE("(%p/%p)->(%p)\n", This, iface, lpData);
2333 if (TRACE_ON(ddraw)) {
2334 TRACE(" viewport is : \n");
2335 TRACE(" - dwX = %ld dwY = %ld\n",
2336 lpData->dwX, lpData->dwY);
2337 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2338 lpData->dwWidth, lpData->dwHeight);
2339 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2340 lpData->dvMinZ, lpData->dvMaxZ);
2344 /* Set the viewport */
2345 if ((lpData->dvMinZ != This->active_viewport.dvMinZ) ||
2346 (lpData->dvMaxZ != This->active_viewport.dvMaxZ)) {
2347 glDepthRange(lpData->dvMinZ, lpData->dvMaxZ);
2349 if ((lpData->dwX != This->active_viewport.dwX) ||
2350 (lpData->dwY != This->active_viewport.dwY) ||
2351 (lpData->dwWidth != This->active_viewport.dwWidth) ||
2352 (lpData->dwHeight != This->active_viewport.dwHeight)) {
2353 glViewport(lpData->dwX,
2354 This->surface->surface_desc.dwHeight - (lpData->dwHeight + lpData->dwY),
2355 lpData->dwWidth, lpData->dwHeight);
2360 This->active_viewport = *lpData;
2365 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2366 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2368 # define XCAST(fun) (void*)
2371 ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
2373 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2374 XCAST(QueryInterface) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface,
2375 XCAST(AddRef) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef,
2376 XCAST(Release) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release,
2377 XCAST(GetCaps) GL_IDirect3DDeviceImpl_7_GetCaps,
2378 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats,
2379 XCAST(BeginScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene,
2380 XCAST(EndScene) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene,
2381 XCAST(GetDirect3D) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D,
2382 XCAST(SetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget,
2383 XCAST(GetRenderTarget) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget,
2384 XCAST(Clear) Main_IDirect3DDeviceImpl_7_Clear,
2385 XCAST(SetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform,
2386 XCAST(GetTransform) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform,
2387 XCAST(SetViewport) GL_IDirect3DDeviceImpl_7_SetViewport,
2388 XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
2389 XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
2390 XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
2391 XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
2392 XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
2393 XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
2394 XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
2395 XCAST(GetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
2396 XCAST(BeginStateBlock) Main_IDirect3DDeviceImpl_7_BeginStateBlock,
2397 XCAST(EndStateBlock) Main_IDirect3DDeviceImpl_7_EndStateBlock,
2398 XCAST(PreLoad) Main_IDirect3DDeviceImpl_7_PreLoad,
2399 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive,
2400 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive,
2401 XCAST(SetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus,
2402 XCAST(GetClipStatus) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus,
2403 XCAST(DrawPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided,
2404 XCAST(DrawIndexedPrimitiveStrided) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided,
2405 XCAST(DrawPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB,
2406 XCAST(DrawIndexedPrimitiveVB) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB,
2407 XCAST(ComputeSphereVisibility) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility,
2408 XCAST(GetTexture) Main_IDirect3DDeviceImpl_7_3T_GetTexture,
2409 XCAST(SetTexture) GL_IDirect3DDeviceImpl_7_3T_SetTexture,
2410 XCAST(GetTextureStageState) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState,
2411 XCAST(SetTextureStageState) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState,
2412 XCAST(ValidateDevice) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice,
2413 XCAST(ApplyStateBlock) Main_IDirect3DDeviceImpl_7_ApplyStateBlock,
2414 XCAST(CaptureStateBlock) Main_IDirect3DDeviceImpl_7_CaptureStateBlock,
2415 XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
2416 XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
2417 XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
2418 XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
2419 XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
2420 XCAST(SetClipPlane) GL_IDirect3DDeviceImpl_7_SetClipPlane,
2421 XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
2422 XCAST(GetInfo) Main_IDirect3DDeviceImpl_7_GetInfo,
2425 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2430 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2431 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2433 # define XCAST(fun) (void*)
2436 ICOM_VTABLE(IDirect3DDevice3) VTABLE_IDirect3DDevice3 =
2438 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2439 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_3_QueryInterface,
2440 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_3_AddRef,
2441 XCAST(Release) Thunk_IDirect3DDeviceImpl_3_Release,
2442 XCAST(GetCaps) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps,
2443 XCAST(GetStats) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats,
2444 XCAST(AddViewport) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport,
2445 XCAST(DeleteViewport) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport,
2446 XCAST(NextViewport) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport,
2447 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats,
2448 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_3_BeginScene,
2449 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_3_EndScene,
2450 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_3_GetDirect3D,
2451 XCAST(SetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport,
2452 XCAST(GetCurrentViewport) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport,
2453 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget,
2454 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget,
2455 XCAST(Begin) Main_IDirect3DDeviceImpl_3_Begin,
2456 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_3_BeginIndexed,
2457 XCAST(Vertex) Main_IDirect3DDeviceImpl_3_2T_Vertex,
2458 XCAST(Index) Main_IDirect3DDeviceImpl_3_2T_Index,
2459 XCAST(End) Main_IDirect3DDeviceImpl_3_2T_End,
2460 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_3_GetRenderState,
2461 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_3_SetRenderState,
2462 XCAST(GetLightState) Main_IDirect3DDeviceImpl_3_2T_GetLightState,
2463 XCAST(SetLightState) GL_IDirect3DDeviceImpl_3_2T_SetLightState,
2464 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_3_SetTransform,
2465 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_3_GetTransform,
2466 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform,
2467 XCAST(DrawPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive,
2468 XCAST(DrawIndexedPrimitive) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive,
2469 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_3_SetClipStatus,
2470 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_3_GetClipStatus,
2471 XCAST(DrawPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided,
2472 XCAST(DrawIndexedPrimitiveStrided) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided,
2473 XCAST(DrawPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB,
2474 XCAST(DrawIndexedPrimitiveVB) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB,
2475 XCAST(ComputeSphereVisibility) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility,
2476 XCAST(GetTexture) Thunk_IDirect3DDeviceImpl_3_GetTexture,
2477 XCAST(SetTexture) Thunk_IDirect3DDeviceImpl_3_SetTexture,
2478 XCAST(GetTextureStageState) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState,
2479 XCAST(SetTextureStageState) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState,
2480 XCAST(ValidateDevice) Thunk_IDirect3DDeviceImpl_3_ValidateDevice,
2483 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2488 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2489 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2491 # define XCAST(fun) (void*)
2494 ICOM_VTABLE(IDirect3DDevice2) VTABLE_IDirect3DDevice2 =
2496 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2497 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_2_QueryInterface,
2498 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_2_AddRef,
2499 XCAST(Release) Thunk_IDirect3DDeviceImpl_2_Release,
2500 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_2_GetCaps,
2501 XCAST(SwapTextureHandles) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles,
2502 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_2_GetStats,
2503 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_2_AddViewport,
2504 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_2_DeleteViewport,
2505 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_2_NextViewport,
2506 XCAST(EnumTextureFormats) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats,
2507 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_2_BeginScene,
2508 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_2_EndScene,
2509 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_2_GetDirect3D,
2510 XCAST(SetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport,
2511 XCAST(GetCurrentViewport) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport,
2512 XCAST(SetRenderTarget) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget,
2513 XCAST(GetRenderTarget) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget,
2514 XCAST(Begin) Main_IDirect3DDeviceImpl_2_Begin,
2515 XCAST(BeginIndexed) Main_IDirect3DDeviceImpl_2_BeginIndexed,
2516 XCAST(Vertex) Thunk_IDirect3DDeviceImpl_2_Vertex,
2517 XCAST(Index) Thunk_IDirect3DDeviceImpl_2_Index,
2518 XCAST(End) Thunk_IDirect3DDeviceImpl_2_End,
2519 XCAST(GetRenderState) Thunk_IDirect3DDeviceImpl_2_GetRenderState,
2520 XCAST(SetRenderState) Thunk_IDirect3DDeviceImpl_2_SetRenderState,
2521 XCAST(GetLightState) Thunk_IDirect3DDeviceImpl_2_GetLightState,
2522 XCAST(SetLightState) Thunk_IDirect3DDeviceImpl_2_SetLightState,
2523 XCAST(SetTransform) Thunk_IDirect3DDeviceImpl_2_SetTransform,
2524 XCAST(GetTransform) Thunk_IDirect3DDeviceImpl_2_GetTransform,
2525 XCAST(MultiplyTransform) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform,
2526 XCAST(DrawPrimitive) GL_IDirect3DDeviceImpl_2_DrawPrimitive,
2527 XCAST(DrawIndexedPrimitive) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive,
2528 XCAST(SetClipStatus) Thunk_IDirect3DDeviceImpl_2_SetClipStatus,
2529 XCAST(GetClipStatus) Thunk_IDirect3DDeviceImpl_2_GetClipStatus,
2532 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2537 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2538 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2540 # define XCAST(fun) (void*)
2543 ICOM_VTABLE(IDirect3DDevice) VTABLE_IDirect3DDevice =
2545 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2546 XCAST(QueryInterface) Thunk_IDirect3DDeviceImpl_1_QueryInterface,
2547 XCAST(AddRef) Thunk_IDirect3DDeviceImpl_1_AddRef,
2548 XCAST(Release) Thunk_IDirect3DDeviceImpl_1_Release,
2549 XCAST(Initialize) Main_IDirect3DDeviceImpl_1_Initialize,
2550 XCAST(GetCaps) Thunk_IDirect3DDeviceImpl_1_GetCaps,
2551 XCAST(SwapTextureHandles) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles,
2552 XCAST(CreateExecuteBuffer) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer,
2553 XCAST(GetStats) Thunk_IDirect3DDeviceImpl_1_GetStats,
2554 XCAST(Execute) Main_IDirect3DDeviceImpl_1_Execute,
2555 XCAST(AddViewport) Thunk_IDirect3DDeviceImpl_1_AddViewport,
2556 XCAST(DeleteViewport) Thunk_IDirect3DDeviceImpl_1_DeleteViewport,
2557 XCAST(NextViewport) Thunk_IDirect3DDeviceImpl_1_NextViewport,
2558 XCAST(Pick) Main_IDirect3DDeviceImpl_1_Pick,
2559 XCAST(GetPickRecords) Main_IDirect3DDeviceImpl_1_GetPickRecords,
2560 XCAST(EnumTextureFormats) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats,
2561 XCAST(CreateMatrix) Main_IDirect3DDeviceImpl_1_CreateMatrix,
2562 XCAST(SetMatrix) Main_IDirect3DDeviceImpl_1_SetMatrix,
2563 XCAST(GetMatrix) Main_IDirect3DDeviceImpl_1_GetMatrix,
2564 XCAST(DeleteMatrix) Main_IDirect3DDeviceImpl_1_DeleteMatrix,
2565 XCAST(BeginScene) Thunk_IDirect3DDeviceImpl_1_BeginScene,
2566 XCAST(EndScene) Thunk_IDirect3DDeviceImpl_1_EndScene,
2567 XCAST(GetDirect3D) Thunk_IDirect3DDeviceImpl_1_GetDirect3D,
2570 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2574 static HRESULT d3ddevice_clear(IDirect3DDeviceImpl *This,
2575 WINE_GL_BUFFER_TYPE buffer_type,
2583 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
2584 GLbitfield bitfield = 0;
2588 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2589 if (TRACE_ON(ddraw)) {
2592 TRACE(" rectangles : \n");
2593 for (i = 0; i < dwCount; i++) {
2594 TRACE(" - %ld x %ld %ld x %ld\n", lpRects[i].u1.x1, lpRects[i].u2.y1, lpRects[i].u3.x2, lpRects[i].u4.y2);
2603 rect.u3.x2 = This->surface->surface_desc.dwWidth;
2604 rect.u4.y2 = This->surface->surface_desc.dwHeight;
2608 /* Clears the screen */
2611 if (dwFlags & D3DCLEAR_TARGET) {
2612 if (glThis->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
2613 /* TODO: optimize here the case where Clear changes all the screen... */
2614 This->flush_to_framebuffer(This, &(glThis->lock_rect[buffer_type]), glThis->lock_surf[buffer_type]);
2616 glThis->state[buffer_type] = SURFACE_GL;
2619 if (dwFlags & D3DCLEAR_ZBUFFER) {
2620 bitfield |= GL_DEPTH_BUFFER_BIT;
2621 if (glThis->depth_mask == FALSE) {
2622 glDepthMask(GL_TRUE); /* Enables Z writing to be sure to delete also the Z buffer */
2624 if (dvZ != glThis->prev_clear_Z) {
2626 glThis->prev_clear_Z = dvZ;
2628 TRACE(" depth value : %f\n", dvZ);
2630 if (dwFlags & D3DCLEAR_STENCIL) {
2631 bitfield |= GL_STENCIL_BUFFER_BIT;
2632 if (dwStencil != glThis->prev_clear_stencil) {
2633 glClearStencil(dwStencil);
2634 glThis->prev_clear_stencil = dwStencil;
2636 TRACE(" stencil value : %ld\n", dwStencil);
2638 if (dwFlags & D3DCLEAR_TARGET) {
2639 bitfield |= GL_COLOR_BUFFER_BIT;
2640 if (dwColor != glThis->prev_clear_color) {
2641 glClearColor(((dwColor >> 16) & 0xFF) / 255.0,
2642 ((dwColor >> 8) & 0xFF) / 255.0,
2643 ((dwColor >> 0) & 0xFF) / 255.0,
2644 ((dwColor >> 24) & 0xFF) / 255.0);
2645 glThis->prev_clear_color = dwColor;
2647 TRACE(" color value (ARGB) : %08lx\n", dwColor);
2650 glEnable(GL_SCISSOR_TEST);
2651 for (i = 0; i < dwCount; i++) {
2652 glScissor(lpRects[i].u1.x1, This->surface->surface_desc.dwHeight - lpRects[i].u4.y2,
2653 lpRects[i].u3.x2 - lpRects[i].u1.x1, lpRects[i].u4.y2 - lpRects[i].u2.y1);
2656 glDisable(GL_SCISSOR_TEST);
2658 if (dwFlags & D3DCLEAR_ZBUFFER) {
2659 if (glThis->depth_mask == FALSE) glDepthMask(GL_FALSE);
2667 static HRESULT d3ddevice_clear_back(IDirect3DDeviceImpl *This,
2675 return d3ddevice_clear(This, WINE_GL_BUFFER_BACK, dwCount, lpRects, dwFlags, dwColor, dvZ, dwStencil);
2679 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl *This,
2680 WINE_GL_BUFFER_TYPE *buffer_type_p, D3DRECT *rect)
2682 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2683 WINE_GL_BUFFER_TYPE buffer_type;
2685 /* First check if we BLT to the backbuffer... */
2686 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2687 buffer_type = WINE_GL_BUFFER_BACK;
2688 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2689 buffer_type = WINE_GL_BUFFER_FRONT;
2691 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2692 return DDERR_INVALIDPARAMS;
2695 if ((gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) &&
2696 (rect->u1.x1 >= gl_d3d_dev->lock_rect[buffer_type].left) &&
2697 (rect->u2.y1 >= gl_d3d_dev->lock_rect[buffer_type].top) &&
2698 (rect->u3.x2 <= gl_d3d_dev->lock_rect[buffer_type].right) &&
2699 (rect->u4.y2 <= gl_d3d_dev->lock_rect[buffer_type].bottom)) {
2700 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2703 return DDERR_INVALIDPARAMS;
2705 *buffer_type_p = buffer_type;
2711 d3ddevice_blt(IDirectDrawSurfaceImpl *This, LPRECT rdst,
2712 LPDIRECTDRAWSURFACE7 src, LPRECT rsrc,
2713 DWORD dwFlags, LPDDBLTFX lpbltfx)
2715 WINE_GL_BUFFER_TYPE buffer_type;
2719 rect.u1.x1 = rdst->left;
2720 rect.u2.y1 = rdst->top;
2721 rect.u3.x2 = rdst->right;
2722 rect.u4.y2 = rdst->bottom;
2726 rect.u3.x2 = This->surface_desc.dwWidth;
2727 rect.u4.y2 = This->surface_desc.dwHeight;
2730 if (setup_rect_and_surface_for_blt(This, &buffer_type, &rect) != DD_OK) return DDERR_INVALIDPARAMS;
2732 if (dwFlags & DDBLT_COLORFILL) {
2733 /* This is easy to handle for the D3D Device... */
2737 /* The color as given in the Blt function is in the format of the frame-buffer...
2738 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2740 if (This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) {
2741 if (This->palette) {
2742 color = ((0xFF000000) |
2743 (This->palette->palents[lpbltfx->u5.dwFillColor].peRed << 16) |
2744 (This->palette->palents[lpbltfx->u5.dwFillColor].peGreen << 8) |
2745 (This->palette->palents[lpbltfx->u5.dwFillColor].peBlue));
2749 } else if ((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) &&
2750 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
2751 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
2752 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
2753 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
2754 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
2755 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
2756 if (lpbltfx->u5.dwFillColor == 0xFFFF) {
2759 color = ((0xFF000000) |
2760 ((lpbltfx->u5.dwFillColor & 0xF800) << 8) |
2761 ((lpbltfx->u5.dwFillColor & 0x07E0) << 5) |
2762 ((lpbltfx->u5.dwFillColor & 0x001F) << 3));
2764 } else if (((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) ||
2765 (This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24)) &&
2766 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
2767 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
2768 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
2769 color = 0xFF000000 | lpbltfx->u5.dwFillColor;
2771 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2772 return DDERR_INVALIDPARAMS;
2775 ERR("Wrong surface type for BLT override !\n");
2776 return DDERR_INVALIDPARAMS;
2779 TRACE(" executing D3D Device override.\n");
2783 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2784 if (buffer_type == WINE_GL_BUFFER_FRONT)
2785 glDrawBuffer(GL_FRONT);
2787 glDrawBuffer(GL_BACK);
2789 d3ddevice_clear(This->d3ddevice, buffer_type, 1, &rect, D3DCLEAR_TARGET, color, 0.0, 0x00000000);
2791 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2792 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2793 glDrawBuffer(prev_draw);
2798 } else if ((dwFlags & (~(DDBLT_KEYSRC|DDBLT_WAIT|DDBLT_ASYNC))) == 0) {
2799 /* Normal blit without any special case... */
2801 /* And which has a SRC surface */
2802 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
2804 if ((src_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_3DDEVICE) &&
2805 (src_impl->d3ddevice == This->d3ddevice) &&
2806 ((dwFlags & DDBLT_KEYSRC) == 0)) {
2807 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
2811 WINE_GL_BUFFER_TYPE src_buffer_type;
2812 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2818 src_rect.u1.x1 = rsrc->left;
2819 src_rect.u2.y1 = rsrc->top;
2820 src_rect.u3.x2 = rsrc->right;
2821 src_rect.u4.y2 = rsrc->bottom;
2825 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
2826 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
2829 width = src_rect.u3.x2 - src_rect.u1.x1;
2830 height = src_rect.u4.y2 - src_rect.u2.y1;
2832 if ((width != (rect.u3.x2 - rect.u1.x1)) ||
2833 (height != (rect.u4.y2 - rect.u2.y1))) {
2834 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
2835 return DDERR_INVALIDPARAMS;
2838 /* First check if we BLT from the backbuffer... */
2839 if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) != 0) {
2840 src_buffer_type = WINE_GL_BUFFER_BACK;
2841 } else if ((src_impl->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
2842 src_buffer_type = WINE_GL_BUFFER_FRONT;
2844 ERR("Unexpected case in direct buffer to buffer copy !\n");
2845 return DDERR_INVALIDPARAMS;
2848 TRACE(" using direct buffer to buffer copy.\n");
2852 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, FALSE, &initial);
2854 if (upload_surface_to_tex_memory_init(This, 0, &gl_d3d_dev->current_internal_format,
2855 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2856 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
2858 return DDERR_INVALIDPARAMS;
2861 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2862 if (buffer_type == WINE_GL_BUFFER_FRONT)
2863 glDrawBuffer(GL_FRONT);
2865 glDrawBuffer(GL_BACK);
2867 if (src_buffer_type == WINE_GL_BUFFER_FRONT)
2868 glReadBuffer(GL_FRONT);
2870 glReadBuffer(GL_BACK);
2872 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
2873 And directly re-draws this on the destination buffer. */
2874 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
2877 if ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwHeight)
2878 get_height = src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y);
2880 get_height = UNLOCK_TEX_SIZE;
2882 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
2885 if ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE) > src_impl->surface_desc.dwWidth)
2886 get_width = src_impl->surface_desc.dwWidth - (src_rect.u1.x1 + x);
2888 get_width = UNLOCK_TEX_SIZE;
2890 glCopyTexSubImage2D(GL_TEXTURE_2D, 0,
2891 0, UNLOCK_TEX_SIZE - get_height,
2892 src_rect.u1.x1 + x, src_impl->surface_desc.dwHeight - (src_rect.u2.y1 + y + get_height),
2893 get_width, get_height);
2896 glTexCoord2f(0.0, 0.0);
2897 glVertex3d(rect.u1.x1 + x,
2898 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2900 glTexCoord2f(1.0, 0.0);
2901 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2902 rect.u2.y1 + y + UNLOCK_TEX_SIZE,
2904 glTexCoord2f(1.0, 1.0);
2905 glVertex3d(rect.u1.x1 + x + UNLOCK_TEX_SIZE,
2908 glTexCoord2f(0.0, 1.0);
2909 glVertex3d(rect.u1.x1 + x,
2916 upload_surface_to_tex_memory_release();
2917 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, FALSE);
2919 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
2920 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
2921 glDrawBuffer(prev_draw);
2927 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
2928 (this prevents calling glReadPixels) */
2932 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
2936 double x_stretch, y_stretch;
2939 src_rect.u1.x1 = rsrc->left;
2940 src_rect.u2.y1 = rsrc->top;
2941 src_rect.u3.x2 = rsrc->right;
2942 src_rect.u4.y2 = rsrc->bottom;
2946 src_rect.u3.x2 = src_impl->surface_desc.dwWidth;
2947 src_rect.u4.y2 = src_impl->surface_desc.dwHeight;
2950 width = src_rect.u3.x2 - src_rect.u1.x1;
2951 height = src_rect.u4.y2 - src_rect.u2.y1;
2953 x_stretch = (double) (rect.u3.x2 - rect.u1.x1) / (double) width;
2954 y_stretch = (double) (rect.u4.y2 - rect.u2.y1) / (double) height;
2956 TRACE(" using memory to buffer Blt overide.\n");
2960 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, (LPCRECT) &rect, ((dwFlags & DDBLT_KEYSRC) != 0), &initial);
2962 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
2963 initial, ((dwFlags & DDBLT_KEYSRC) != 0), UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
2964 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
2966 return DDERR_INVALIDPARAMS;
2969 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
2970 if (buffer_type == WINE_GL_BUFFER_FRONT)
2971 glDrawBuffer(GL_FRONT);
2973 glDrawBuffer(GL_BACK);
2975 /* Now the serious stuff happens. This is basically the same code that for the memory
2976 flush to frame buffer ... with stretching and different rectangles added :-) */
2977 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
2980 flush_rect.top = src_rect.u2.y1 + y;
2981 flush_rect.bottom = ((src_rect.u2.y1 + y + UNLOCK_TEX_SIZE > src_rect.u4.y2) ?
2983 (src_rect.u2.y1 + y + UNLOCK_TEX_SIZE));
2985 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
2986 flush_rect.left = src_rect.u1.x1 + x;
2987 flush_rect.right = ((src_rect.u1.x1 + x + UNLOCK_TEX_SIZE > src_rect.u3.x2) ?
2989 (src_rect.u1.x1 + x + UNLOCK_TEX_SIZE));
2991 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
2994 glTexCoord2f(0.0, 0.0);
2995 glVertex3d(rect.u1.x1 + (x * x_stretch),
2996 rect.u2.y1 + (y * y_stretch),
2998 glTexCoord2f(1.0, 0.0);
2999 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3000 rect.u2.y1 + (y * y_stretch),
3002 glTexCoord2f(1.0, 1.0);
3003 glVertex3d(rect.u1.x1 + ((x + UNLOCK_TEX_SIZE) * x_stretch),
3004 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3006 glTexCoord2f(0.0, 1.0);
3007 glVertex3d(rect.u1.x1 + (x * x_stretch),
3008 rect.u2.y1 + ((y + UNLOCK_TEX_SIZE) * y_stretch),
3014 upload_surface_to_tex_memory_release();
3015 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, ((dwFlags & DDBLT_KEYSRC) != 0));
3017 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3018 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3019 glDrawBuffer(prev_draw);
3027 return DDERR_INVALIDPARAMS;
3031 d3ddevice_bltfast(IDirectDrawSurfaceImpl *This, DWORD dstx,
3032 DWORD dsty, LPDIRECTDRAWSURFACE7 src,
3033 LPRECT rsrc, DWORD trans)
3037 IDirectDrawSurfaceImpl *src_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, src);
3038 IDirect3DDeviceGLImpl *gl_d3d_dev = (IDirect3DDeviceGLImpl *) This->d3ddevice;
3039 WINE_GL_BUFFER_TYPE buffer_type;
3043 int width, height, x, y;
3045 /* Cannot support DSTCOLORKEY blitting... */
3046 if ((trans & DDBLTFAST_DESTCOLORKEY) != 0) return DDERR_INVALIDPARAMS;
3049 WARN("rsrc is NULL - getting the whole surface !!\n");
3051 rsrc->left = rsrc->top = 0;
3052 rsrc->right = src_impl->surface_desc.dwWidth;
3053 rsrc->bottom = src_impl->surface_desc.dwHeight;
3061 rdst.right = dstx + (rsrc->right - rsrc->left);
3062 if (rdst.right > This->surface_desc.dwWidth) {
3063 rsrc->right -= (This->surface_desc.dwWidth - rdst.right);
3064 rdst.right = This->surface_desc.dwWidth;
3066 rdst.bottom = dsty + (rsrc->bottom - rsrc->top);
3067 if (rdst.bottom > This->surface_desc.dwHeight) {
3068 rsrc->bottom -= (This->surface_desc.dwHeight - rdst.bottom);
3069 rdst.bottom = This->surface_desc.dwHeight;
3072 width = rsrc->right - rsrc->left;
3073 height = rsrc->bottom - rsrc->top;
3075 if (setup_rect_and_surface_for_blt(This, &buffer_type, (D3DRECT *) &rdst) != DD_OK) return DDERR_INVALIDPARAMS;
3077 TRACE(" using BltFast memory to frame buffer overide.\n");
3081 opt_bitmap = d3ddevice_set_state_for_flush(This->d3ddevice, &rdst, (trans & DDBLTFAST_SRCCOLORKEY) != 0, &initial);
3083 if (upload_surface_to_tex_memory_init(src_impl, 0, &gl_d3d_dev->current_internal_format,
3084 initial, (trans & DDBLTFAST_SRCCOLORKEY) != 0,
3085 UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3086 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3088 return DDERR_INVALIDPARAMS;
3091 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3092 if (buffer_type == WINE_GL_BUFFER_FRONT)
3093 glDrawBuffer(GL_FRONT);
3095 glDrawBuffer(GL_BACK);
3097 /* Now the serious stuff happens. This is basically the same code that for the memory
3098 flush to frame buffer but with different rectangles for source and destination :-) */
3099 for (y = 0; y < height; y += UNLOCK_TEX_SIZE) {
3102 flush_rect.top = rsrc->top + y;
3103 flush_rect.bottom = ((rsrc->top + y + UNLOCK_TEX_SIZE > rsrc->bottom) ?
3105 (rsrc->top + y + UNLOCK_TEX_SIZE));
3107 for (x = 0; x < width; x += UNLOCK_TEX_SIZE) {
3108 flush_rect.left = rsrc->left + x;
3109 flush_rect.right = ((rsrc->left + x + UNLOCK_TEX_SIZE > rsrc->right) ?
3111 (rsrc->left + x + UNLOCK_TEX_SIZE));
3113 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3116 glTexCoord2f(0.0, 0.0);
3117 glVertex3d(rdst.left + x,
3120 glTexCoord2f(1.0, 0.0);
3121 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3124 glTexCoord2f(1.0, 1.0);
3125 glVertex3d(rdst.left + (x + UNLOCK_TEX_SIZE),
3126 rdst.top + (y + UNLOCK_TEX_SIZE),
3128 glTexCoord2f(0.0, 1.0);
3129 glVertex3d(rdst.left + x,
3130 rdst.top + (y + UNLOCK_TEX_SIZE),
3136 upload_surface_to_tex_memory_release();
3137 d3ddevice_restore_state_after_flush(This->d3ddevice, opt_bitmap, (trans & DDBLTFAST_SRCCOLORKEY) != 0);
3139 if (((buffer_type == WINE_GL_BUFFER_FRONT) && (prev_draw == GL_BACK)) ||
3140 ((buffer_type == WINE_GL_BUFFER_BACK) && (prev_draw == GL_FRONT)))
3141 glDrawBuffer(prev_draw);
3149 d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
3151 GLfloat height, width;
3152 GLfloat trans_mat[16];
3154 TRACE("(%p)\n", This);
3156 width = This->surface->surface_desc.dwWidth;
3157 height = This->surface->surface_desc.dwHeight;
3159 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3160 to OpenGL screen coordinates (ie the upper left corner is not the same).
3161 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
3162 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
3163 trans_mat[ 0] = 2.0 / width; trans_mat[ 4] = 0.0; trans_mat[ 8] = 0.0; trans_mat[12] = -1.0;
3164 trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
3165 trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
3166 trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
3169 glMatrixMode(GL_MODELVIEW);
3171 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3172 Correctness Tips section).
3174 Basically, from what I understood, if the game does not filter the font texture,
3175 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3176 one and we will have strange artifacts (as the rounding and stuff may give different results
3177 for different pixels, ie sometimes take the left pixel, sometimes the right).
3179 glTranslatef(0.375, 0.375, 0);
3180 glMatrixMode(GL_PROJECTION);
3181 glLoadMatrixf(trans_mat);
3186 d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
3187 D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
3189 TRACE("(%p,%08lx,%p,%p,%p)\n", This, matrices, world_mat, view_mat, proj_mat);
3192 if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
3193 glMatrixMode(GL_MODELVIEW);
3194 glLoadMatrixf((float *) view_mat);
3196 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3197 if (This->state_block.render_state[D3DRENDERSTATE_CLIPPING - 1] != FALSE) {
3200 for (i = 0, runner = 0x00000001; i < This->max_clipping_planes; i++, runner <<= 1) {
3201 if (runner & This->state_block.render_state[D3DRENDERSTATE_CLIPPLANEENABLE - 1]) {
3204 plane[0] = This->clipping_planes[i].plane[0];
3205 plane[1] = This->clipping_planes[i].plane[1];
3206 plane[2] = This->clipping_planes[i].plane[2];
3207 plane[3] = This->clipping_planes[i].plane[3];
3209 glClipPlane( GL_CLIP_PLANE0 + i, (const GLdouble*) (&plane) );
3213 if (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] != FALSE) {
3217 for (i = 0, runner = 0x00000001; i < MAX_LIGHTS; i++, runner <<= 1) {
3218 if (runner & This->active_lights) {
3219 switch (This->light_parameters[i].dltType) {
3220 case D3DLIGHT_DIRECTIONAL: {
3222 float cut_off = 180.0;
3224 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3225 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3226 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3227 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3229 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3230 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3231 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3233 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) direction);
3236 case D3DLIGHT_POINT: {
3238 float cut_off = 180.0;
3240 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3241 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3242 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3243 position[0] = This->light_parameters[i].dvPosition.u1.x;
3244 position[1] = This->light_parameters[i].dvPosition.u2.y;
3245 position[2] = This->light_parameters[i].dvPosition.u3.z;
3247 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3248 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3249 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3250 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3251 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3254 case D3DLIGHT_SPOT: {
3257 float cut_off = 90.0 * (This->light_parameters[i].dvPhi / M_PI);
3259 glLightfv(GL_LIGHT0 + i, GL_AMBIENT, (float *) &(This->light_parameters[i].dcvAmbient));
3260 glLightfv(GL_LIGHT0 + i, GL_DIFFUSE, (float *) &(This->light_parameters[i].dcvDiffuse));
3261 glLightfv(GL_LIGHT0 + i, GL_SPECULAR, (float *) &(This->light_parameters[i].dcvSpecular));
3263 direction[0] = This->light_parameters[i].dvDirection.u1.x;
3264 direction[1] = This->light_parameters[i].dvDirection.u2.y;
3265 direction[2] = This->light_parameters[i].dvDirection.u3.z;
3267 glLightfv(GL_LIGHT0 + i, GL_SPOT_DIRECTION, (float *) direction);
3268 position[0] = This->light_parameters[i].dvPosition.u1.x;
3269 position[1] = This->light_parameters[i].dvPosition.u2.y;
3270 position[2] = This->light_parameters[i].dvPosition.u3.z;
3272 glLightfv(GL_LIGHT0 + i, GL_POSITION, (float *) position);
3273 glLightfv(GL_LIGHT0 + i, GL_CONSTANT_ATTENUATION, &(This->light_parameters[i].dvAttenuation0));
3274 glLightfv(GL_LIGHT0 + i, GL_LINEAR_ATTENUATION, &(This->light_parameters[i].dvAttenuation1));
3275 glLightfv(GL_LIGHT0 + i, GL_QUADRATIC_ATTENUATION, &(This->light_parameters[i].dvAttenuation2));
3276 glLightfv(GL_LIGHT0 + i, GL_SPOT_CUTOFF, &cut_off);
3277 glLightfv(GL_LIGHT0 + i, GL_SPOT_EXPONENT, &(This->light_parameters[i].dvFalloff));
3281 /* No warning here as it's already done at light setting */
3288 glMultMatrixf((float *) world_mat);
3290 if ((matrices & PROJMAT_CHANGED) != 0) {
3291 glMatrixMode(GL_PROJECTION);
3292 glLoadMatrixf((float *) proj_mat);
3298 d3ddevice_matrices_updated(IDirect3DDeviceImpl *This, DWORD matrices)
3300 IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
3301 DWORD tex_mat, tex_stage;
3303 TRACE("(%p,%08lx)\n", This, matrices);
3305 if (matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED|PROJMAT_CHANGED)) {
3306 if (glThis->transform_state == GL_TRANSFORM_NORMAL) {
3307 /* This will force an update of the transform state at the next drawing. */
3308 glThis->transform_state = GL_TRANSFORM_NONE;
3311 if (matrices & (TEXMAT0_CHANGED|TEXMAT1_CHANGED|TEXMAT2_CHANGED|TEXMAT3_CHANGED|
3312 TEXMAT4_CHANGED|TEXMAT5_CHANGED|TEXMAT6_CHANGED|TEXMAT7_CHANGED))
3315 for (tex_mat = TEXMAT0_CHANGED, tex_stage = 0; tex_mat <= TEXMAT7_CHANGED; tex_mat <<= 1, tex_stage++) {
3316 GLenum unit = GL_TEXTURE0_WINE + tex_stage;
3317 if (matrices & tex_mat) {
3318 if (This->state_block.texture_stage_state[tex_stage][D3DTSS_TEXTURETRANSFORMFLAGS - 1] != D3DTTFF_DISABLE) {
3319 int is_identity = (memcmp(This->tex_mat[tex_stage], id_mat, 16 * sizeof(D3DVALUE)) != 0);
3321 if (This->tex_mat_is_identity[tex_stage] != is_identity) {
3322 if (glThis->current_active_tex_unit != unit) {
3323 GL_extensions.glActiveTexture(unit);
3324 glThis->current_active_tex_unit = unit;
3326 glMatrixMode(GL_TEXTURE);
3327 glLoadMatrixf((float *) This->tex_mat[tex_stage]);
3329 This->tex_mat_is_identity[tex_stage] = is_identity;
3331 if (This->tex_mat_is_identity[tex_stage] == FALSE) {
3332 if (glThis->current_active_tex_unit != unit) {
3333 GL_extensions.glActiveTexture(unit);
3334 glThis->current_active_tex_unit = unit;
3336 glMatrixMode(GL_TEXTURE);
3338 This->tex_mat_is_identity[tex_stage] = TRUE;
3347 /* TODO for both these functions :
3348 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3349 by other OpenGL code in D3D
3350 - handle the case where no 'Begin / EndScene' was done between two locks
3351 - handle the rectangles in the unlock too
3352 - handle pitch correctly...
3354 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect, DWORD dwFlags)
3356 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3357 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3358 WINE_GL_BUFFER_TYPE buffer_type;
3361 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3362 buffer_type = WINE_GL_BUFFER_FRONT;
3363 if ((gl_d3d_dev->state[WINE_GL_BUFFER_FRONT] != SURFACE_GL) &&
3364 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] != This)) {
3365 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3367 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_FRONT] = This;
3368 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3369 buffer_type = WINE_GL_BUFFER_BACK;
3370 if ((gl_d3d_dev->state[WINE_GL_BUFFER_BACK] != SURFACE_GL) &&
3371 (gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] != This)) {
3372 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3374 gl_d3d_dev->lock_surf[WINE_GL_BUFFER_BACK] = This;
3376 ERR("Wrong surface type for locking !\n");
3380 if (pRect == NULL) {
3383 loc_rect.bottom = This->surface_desc.dwHeight;
3384 loc_rect.right = This->surface_desc.dwWidth;
3388 /* Try to acquire the device critical section */
3389 EnterCriticalSection(&(d3d_dev->crit));
3391 if (gl_d3d_dev->lock_rect_valid[buffer_type] == TRUE) {
3392 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3393 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3395 gl_d3d_dev->lock_rect_valid[buffer_type] = TRUE;
3397 if (gl_d3d_dev->state[buffer_type] != SURFACE_GL) {
3398 /* Check if the new rectangle is in the previous one or not.
3399 If it is not, flush first the previous locks on screen.
3401 if ((pRect->top < gl_d3d_dev->lock_rect[buffer_type].top) ||
3402 (pRect->left < gl_d3d_dev->lock_rect[buffer_type].left) ||
3403 (pRect->right > gl_d3d_dev->lock_rect[buffer_type].right) ||
3404 (pRect->bottom > gl_d3d_dev->lock_rect[buffer_type].bottom)) {
3405 if (gl_d3d_dev->state[buffer_type] == SURFACE_MEMORY_DIRTY) {
3406 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3407 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3408 pRect->left, pRect->top, pRect->right, pRect->bottom,
3409 gl_d3d_dev->lock_rect[buffer_type].left, gl_d3d_dev->lock_rect[buffer_type].top,
3410 gl_d3d_dev->lock_rect[buffer_type].right, gl_d3d_dev->lock_rect[buffer_type].bottom);
3411 d3d_dev->flush_to_framebuffer(d3d_dev, &(gl_d3d_dev->lock_rect[buffer_type]), gl_d3d_dev->lock_surf[buffer_type]);
3413 gl_d3d_dev->state[buffer_type] = SURFACE_GL;
3414 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3416 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3418 gl_d3d_dev->lock_rect[buffer_type] = *pRect;
3421 if (gl_d3d_dev->state[buffer_type] == SURFACE_GL) {
3422 /* If the surface is already in memory, no need to do anything here... */
3423 GLenum buffer_format;
3424 GLenum buffer_color;
3428 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"),
3429 pRect->left, pRect->top, pRect->right, pRect->bottom);
3431 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3432 may only write to the device... But when we will blit it back to the screen, we need
3433 also to blit correctly the parts the application did not overwrite... */
3435 if (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_RGB) != 0) &&
3436 (((This->surface_desc.u4.ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS) == 0) ||
3437 (This->surface_desc.u4.ddpfPixelFormat.u5.dwRGBAlphaBitMask == 0x00000000))) {
3438 if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 16) &&
3439 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xF800) &&
3440 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x07E0) &&
3441 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x001F)) {
3442 buffer_format = GL_UNSIGNED_SHORT_5_6_5;
3443 buffer_color = GL_RGB;
3444 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 24) &&
3445 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0xFF0000) &&
3446 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x00FF00) &&
3447 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x0000FF)) {
3448 buffer_format = GL_UNSIGNED_BYTE;
3449 buffer_color = GL_RGB;
3450 } else if ((This->surface_desc.u4.ddpfPixelFormat.u1.dwRGBBitCount == 32) &&
3451 (This->surface_desc.u4.ddpfPixelFormat.u2.dwRBitMask == 0x00FF0000) &&
3452 (This->surface_desc.u4.ddpfPixelFormat.u3.dwGBitMask == 0x0000FF00) &&
3453 (This->surface_desc.u4.ddpfPixelFormat.u4.dwBBitMask == 0x000000FF)) {
3454 buffer_format = GL_UNSIGNED_INT_8_8_8_8_REV;
3455 buffer_color = GL_BGRA;
3457 ERR(" unsupported pixel format at device locking.\n");
3461 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3467 if (buffer_type == WINE_GL_BUFFER_FRONT)
3468 /* Application wants to lock the front buffer */
3469 glReadBuffer(GL_FRONT);
3471 /* Application wants to lock the back buffer */
3472 glReadBuffer(GL_BACK);
3474 dst = ((char *)This->surface_desc.lpSurface) +
3475 (pRect->top * This->surface_desc.u1.lPitch) + (pRect->left * GET_BPP(This->surface_desc));
3476 for (y = (This->surface_desc.dwHeight - pRect->top - 1);
3477 y >= ((int) This->surface_desc.dwHeight - (int) pRect->bottom);
3479 glReadPixels(pRect->left, y,
3480 pRect->right - pRect->left, 1,
3481 buffer_color, buffer_format, dst);
3482 dst += This->surface_desc.u1.lPitch;
3485 gl_d3d_dev->state[buffer_type] = SURFACE_MEMORY;
3488 /* I keep this code here as it's very useful to debug :-) */
3490 static int flush_count = 0;
3494 if ((++flush_count % 50) == 0) {
3495 sprintf(buf, "lock_%06d.pnm", flush_count);
3496 f = fopen(buf, "wb");
3497 DDRAW_dump_surface_to_disk(This, f);
3506 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCRECT pRect, IDirectDrawSurfaceImpl *surf) {
3508 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3513 /* Note : no need here to lock the 'device critical section' as we are already protected by
3514 the GL critical section. */
3516 if (pRect == NULL) {
3519 loc_rect.bottom = d3d_dev->surface->surface_desc.dwHeight;
3520 loc_rect.right = d3d_dev->surface->surface_desc.dwWidth;
3524 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect->top, pRect->left, pRect->right, pRect->bottom);
3526 opt_bitmap = d3ddevice_set_state_for_flush(d3d_dev, pRect, FALSE, &initial);
3528 if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
3529 initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != DD_OK) {
3530 ERR(" unsupported pixel format at frame buffer flush.\n");
3534 for (y = pRect->top; y < pRect->bottom; y += UNLOCK_TEX_SIZE) {
3538 flush_rect.bottom = (y + UNLOCK_TEX_SIZE > pRect->bottom) ? pRect->bottom : (y + UNLOCK_TEX_SIZE);
3540 for (x = pRect->left; x < pRect->right; x += UNLOCK_TEX_SIZE) {
3541 /* First, upload the texture... */
3542 flush_rect.left = x;
3543 flush_rect.right = (x + UNLOCK_TEX_SIZE > pRect->right) ? pRect->right : (x + UNLOCK_TEX_SIZE);
3545 upload_surface_to_tex_memory(&flush_rect, 0, 0, &(gl_d3d_dev->surface_ptr));
3548 glTexCoord2f(0.0, 0.0);
3549 glVertex3d(x, y, 0.5);
3550 glTexCoord2f(1.0, 0.0);
3551 glVertex3d(x + UNLOCK_TEX_SIZE, y, 0.5);
3552 glTexCoord2f(1.0, 1.0);
3553 glVertex3d(x + UNLOCK_TEX_SIZE, y + UNLOCK_TEX_SIZE, 0.5);
3554 glTexCoord2f(0.0, 1.0);
3555 glVertex3d(x, y + UNLOCK_TEX_SIZE, 0.5);
3560 upload_surface_to_tex_memory_release();
3561 d3ddevice_restore_state_after_flush(d3d_dev, opt_bitmap, FALSE);
3564 /* I keep this code here as it's very useful to debug :-) */
3566 static int flush_count = 0;
3570 if ((++flush_count % 50) == 0) {
3571 sprintf(buf, "flush_%06d.pnm", flush_count);
3572 f = fopen(buf, "wb");
3573 DDRAW_dump_surface_to_disk(surf, f);
3579 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
3581 WINE_GL_BUFFER_TYPE buffer_type;
3582 IDirect3DDeviceImpl *d3d_dev = This->d3ddevice;
3583 IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
3585 if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_FRONTBUFFER|DDSCAPS_PRIMARYSURFACE)) != 0) {
3586 buffer_type = WINE_GL_BUFFER_FRONT;
3587 } else if ((This->surface_desc.ddsCaps.dwCaps & (DDSCAPS_BACKBUFFER)) == (DDSCAPS_BACKBUFFER)) {
3588 buffer_type = WINE_GL_BUFFER_BACK;
3590 ERR("Wrong surface type for locking !\n");
3594 if (gl_d3d_dev->lock_rect_valid[buffer_type] == FALSE) {
3595 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3596 (buffer_type == WINE_GL_BUFFER_BACK ? "back" : "front"));
3598 gl_d3d_dev->lock_rect_valid[buffer_type] = FALSE;
3600 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3601 if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
3602 if (buffer_type == WINE_GL_BUFFER_FRONT) {
3605 TRACE(" flushing front buffer immediatly on screen.\n");
3608 glGetIntegerv(GL_DRAW_BUFFER, &prev_draw);
3609 glDrawBuffer(GL_FRONT);
3610 /* Note: we do not use the application provided lock rectangle but our own stored at
3611 lock time. This is because in old D3D versions, the 'lock' parameter did not
3614 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]);
3615 glDrawBuffer(prev_draw);
3618 gl_d3d_dev->state[WINE_GL_BUFFER_BACK] = SURFACE_MEMORY_DIRTY;
3622 /* And 'frees' the device critical section */
3623 LeaveCriticalSection(&(d3d_dev->crit));
3627 apply_texture_state(IDirect3DDeviceImpl *This)
3631 /* Initialize texture stages states */
3632 for (stage = 0; stage < MAX_TEXTURES; stage++) {
3633 for (state = 0; state < HIGHEST_TEXTURE_STAGE_STATE; state += 1) {
3634 if (This->state_block.set_flags.texture_stage_state[stage][state] == TRUE) {
3635 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This, IDirect3DDevice7),
3636 stage, state + 1, This->state_block.texture_stage_state[stage][state]);
3643 d3ddevice_create(IDirect3DDeviceImpl **obj, IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surface)
3645 IDirect3DDeviceImpl *object;
3646 IDirect3DDeviceGLImpl *gl_object;
3647 IDirectDrawSurfaceImpl *surf;
3652 XVisualInfo template;
3653 GLenum buffer = GL_FRONT;
3656 object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
3657 if (object == NULL) return DDERR_OUTOFMEMORY;
3659 gl_object = (IDirect3DDeviceGLImpl *) object;
3663 object->surface = surface;
3664 object->set_context = set_context;
3665 object->clear = d3ddevice_clear_back;
3666 object->set_matrices = d3ddevice_set_matrices;
3667 object->matrices_updated = d3ddevice_matrices_updated;
3668 object->flush_to_framebuffer = d3ddevice_flush_to_frame_buffer;
3670 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface, d3d);
3672 InitializeCriticalSection(&(object->crit));
3674 TRACE(" device critical section : %p\n", &(object->crit));
3676 device_context = GetDC(surface->ddraw_owner->window);
3677 gl_object->display = get_display(device_context);
3678 gl_object->drawable = get_drawable(device_context);
3679 ReleaseDC(surface->ddraw_owner->window,device_context);
3682 template.visualid = (VisualID)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3683 vis = XGetVisualInfo(gl_object->display, VisualIDMask, &template, &num);
3685 HeapFree(GetProcessHeap(), 0, object);
3686 ERR("No visual found !\n");
3688 return DDERR_INVALIDPARAMS;
3690 TRACE(" visual found\n");
3693 gl_object->gl_context = glXCreateContext(gl_object->display, vis,
3696 if (gl_object->gl_context == NULL) {
3697 HeapFree(GetProcessHeap(), 0, object);
3698 ERR("Error in context creation !\n");
3700 return DDERR_INVALIDPARAMS;
3702 TRACE(" context created (%p)\n", gl_object->gl_context);
3705 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3706 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3707 if ((surf->surface_desc.ddsCaps.dwCaps&(DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) == (DDSCAPS_FLIP|DDSCAPS_FRONTBUFFER)) {
3708 surf->aux_ctx = (LPVOID) object;
3709 surf->aux_data = (LPVOID) gl_object->drawable;
3710 surf->aux_flip = opengl_flip;
3715 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3717 TRACE(" no double buffering : drawing on the front buffer\n");
3721 for (surf = surface; surf != NULL; surf = surf->surface_owner) {
3722 IDirectDrawSurfaceImpl *surf2;
3723 for (surf2 = surf; surf2->prev_attached != NULL; surf2 = surf2->prev_attached) ;
3724 for (; surf2 != NULL; surf2 = surf2->next_attached) {
3725 TRACE(" checking surface %p :", surf2);
3726 if (((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_3DDEVICE)) == (DDSCAPS_3DDEVICE)) &&
3727 ((surf2->surface_desc.ddsCaps.dwCaps & (DDSCAPS_ZBUFFER)) != (DDSCAPS_ZBUFFER))) {
3728 /* Override the Lock / Unlock function for all these surfaces */
3729 surf2->lock_update_prev = surf2->lock_update;
3730 surf2->lock_update = d3ddevice_lock_update;
3731 surf2->unlock_update_prev = surf2->unlock_update;
3732 surf2->unlock_update = d3ddevice_unlock_update;
3733 /* And install also the blt / bltfast overrides */
3734 surf2->aux_blt = d3ddevice_blt;
3735 surf2->aux_bltfast = d3ddevice_bltfast;
3737 TRACE(" overiding direct surface access.\n");
3739 TRACE(" no overide.\n");
3741 surf2->d3ddevice = object;
3745 /* Set the various light parameters */
3746 for (light = 0; light < MAX_LIGHTS; light++) {
3747 /* Only set the fields that are not zero-created */
3748 object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
3749 object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
3750 object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
3751 object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
3752 object->light_parameters[light].dvDirection.u3.z = 1.0;
3755 /* Allocate memory for the matrices */
3756 object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3757 object->view_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3758 object->proj_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3759 memcpy(object->world_mat, id_mat, 16 * sizeof(float));
3760 memcpy(object->view_mat , id_mat, 16 * sizeof(float));
3761 memcpy(object->proj_mat , id_mat, 16 * sizeof(float));
3762 for (tex_num = 0; tex_num < MAX_TEXTURES; tex_num++) {
3763 object->tex_mat[tex_num] = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
3764 memcpy(object->tex_mat[tex_num], id_mat, 16 * sizeof(float));
3765 object->tex_mat_is_identity[tex_num] = TRUE;
3768 /* Initialisation */
3769 TRACE(" setting current context\n");
3770 object->set_context(object);
3771 TRACE(" current context set\n");
3773 /* allocate the clipping planes */
3774 object->max_clipping_planes = opengl_device_caps.wMaxUserClipPlanes;
3775 object->clipping_planes = (d3d7clippingplane*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, object->max_clipping_planes * sizeof(d3d7clippingplane));
3777 glHint(GL_FOG_HINT,GL_NICEST);
3779 /* Initialize the various GL contexts to be in sync with what we store locally */
3782 glClearColor(0.0, 0.0, 0.0, 0.0);
3783 glDepthMask(GL_TRUE);
3784 gl_object->depth_mask = TRUE;
3785 glEnable(GL_DEPTH_TEST);
3786 gl_object->depth_test = TRUE;
3787 glDisable(GL_ALPHA_TEST);
3788 glDisable(GL_STENCIL_TEST);
3789 glDisable(GL_CULL_FACE);
3790 glDisable(GL_LIGHTING);
3791 glDisable(GL_BLEND);
3793 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
3794 gl_object->current_tex_env = GL_REPLACE;
3795 gl_object->current_active_tex_unit = GL_TEXTURE0_WINE;
3796 if (GL_extensions.glActiveTexture != NULL) {
3797 GL_extensions.glActiveTexture(GL_TEXTURE0_WINE);
3800 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
3801 glDrawBuffer(buffer);
3802 glReadBuffer(buffer);
3803 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3806 gl_object->state[WINE_GL_BUFFER_BACK] = SURFACE_GL;
3807 gl_object->state[WINE_GL_BUFFER_FRONT] = SURFACE_GL;
3809 /* fill_device_capabilities(d3d->ddraw); */
3811 ICOM_INIT_INTERFACE(object, IDirect3DDevice, VTABLE_IDirect3DDevice);
3812 ICOM_INIT_INTERFACE(object, IDirect3DDevice2, VTABLE_IDirect3DDevice2);
3813 ICOM_INIT_INTERFACE(object, IDirect3DDevice3, VTABLE_IDirect3DDevice3);
3814 ICOM_INIT_INTERFACE(object, IDirect3DDevice7, VTABLE_IDirect3DDevice7);
3818 TRACE(" creating implementation at %p.\n", *obj);
3820 /* And finally warn D3D that this device is now present */
3821 object->d3d->d3d_added_device(object->d3d, object);
3823 /* FIXME: Should handle other versions than just 7 */
3824 InitDefaultStateBlock(&object->state_block, 7);
3825 /* Apply default render state and texture stage state values */
3826 apply_render_state(object, &object->state_block);
3827 apply_texture_state(object);
3829 /* And fill the fog table with the default fog value */
3830 build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
3835 static void fill_opengl_primcaps(D3DPRIMCAPS *pc)
3837 pc->dwSize = sizeof(*pc);
3838 pc->dwMiscCaps = D3DPMISCCAPS_CONFORMANT | D3DPMISCCAPS_CULLCCW | D3DPMISCCAPS_CULLCW |
3839 D3DPMISCCAPS_LINEPATTERNREP | D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_MASKZ;
3840 pc->dwRasterCaps = D3DPRASTERCAPS_DITHER | D3DPRASTERCAPS_FOGRANGE | D3DPRASTERCAPS_FOGTABLE |
3841 D3DPRASTERCAPS_FOGVERTEX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ZBIAS | D3DPRASTERCAPS_ZTEST | D3DPRASTERCAPS_SUBPIXEL |
3842 D3DPRASTERCAPS_ZFOG;
3843 if (GL_extensions.mipmap_lodbias == TRUE) {
3844 pc->dwRasterCaps |= D3DPRASTERCAPS_MIPMAPLODBIAS;
3846 pc->dwZCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3847 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3848 pc->dwSrcBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_DESTCOLOR | D3DPBLENDCAPS_INVDESTCOLOR |
3849 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3850 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3851 pc->dwDestBlendCaps = D3DPBLENDCAPS_ZERO | D3DPBLENDCAPS_ONE | D3DPBLENDCAPS_SRCCOLOR | D3DPBLENDCAPS_INVSRCCOLOR |
3852 D3DPBLENDCAPS_SRCALPHA | D3DPBLENDCAPS_INVSRCALPHA | D3DPBLENDCAPS_DESTALPHA | D3DPBLENDCAPS_INVDESTALPHA | D3DPBLENDCAPS_SRCALPHASAT |
3853 D3DPBLENDCAPS_BOTHSRCALPHA | D3DPBLENDCAPS_BOTHINVSRCALPHA;
3854 pc->dwAlphaCmpCaps = D3DPCMPCAPS_ALWAYS | D3DPCMPCAPS_EQUAL | D3DPCMPCAPS_GREATER | D3DPCMPCAPS_GREATEREQUAL |
3855 D3DPCMPCAPS_LESS | D3DPCMPCAPS_LESSEQUAL | D3DPCMPCAPS_NEVER | D3DPCMPCAPS_NOTEQUAL;
3856 pc->dwShadeCaps = D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAGOURAUDBLEND | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDRGB |
3857 D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGGOURAUD | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDRGB;
3858 pc->dwTextureCaps = D3DPTEXTURECAPS_ALPHA | D3DPTEXTURECAPS_ALPHAPALETTE | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_PERSPECTIVE |
3859 D3DPTEXTURECAPS_POW2 | D3DPTEXTURECAPS_TRANSPARENCY;
3860 pc->dwTextureFilterCaps = D3DPTFILTERCAPS_LINEAR | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST |
3861 D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_NEAREST | D3DPTFILTERCAPS_MAGFLINEAR |
3862 D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MIPFLINEAR |
3863 D3DPTFILTERCAPS_MIPFPOINT;
3864 pc->dwTextureBlendCaps = D3DPTBLENDCAPS_ADD | D3DPTBLENDCAPS_COPY | D3DPTBLENDCAPS_DECAL | D3DPTBLENDCAPS_DECALALPHA | D3DPTBLENDCAPS_DECALMASK |
3865 D3DPTBLENDCAPS_MODULATE | D3DPTBLENDCAPS_MODULATEALPHA | D3DPTBLENDCAPS_MODULATEMASK;
3866 pc->dwTextureAddressCaps = D3DPTADDRESSCAPS_BORDER | D3DPTADDRESSCAPS_CLAMP | D3DPTADDRESSCAPS_WRAP | D3DPTADDRESSCAPS_INDEPENDENTUV;
3867 if (GL_extensions.mirrored_repeat == TRUE) {
3868 pc->dwTextureAddressCaps |= D3DPTADDRESSCAPS_MIRROR;
3870 pc->dwStippleWidth = 32;
3871 pc->dwStippleHeight = 32;
3874 static void fill_caps(void)
3876 GLint max_clip_planes;
3878 /* Fill first all the fields with default values which will be overriden later on with
3879 correct ones from the GL code
3881 opengl_device_caps.dwDevCaps = D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_EXECUTESYSTEMMEMORY |
3882 D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_TEXTURENONLOCALVIDMEM | D3DDEVCAPS_TEXTURESYSTEMMEMORY |
3883 D3DDEVCAPS_TEXTUREVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY | D3DDEVCAPS_TLVERTEXVIDEOMEMORY |
3884 /* D3D 7 capabilities */
3885 D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_HWRASTERIZATION;
3886 fill_opengl_primcaps(&(opengl_device_caps.dpcLineCaps));
3887 fill_opengl_primcaps(&(opengl_device_caps.dpcTriCaps));
3888 opengl_device_caps.dwDeviceRenderBitDepth = DDBD_16|DDBD_24|DDBD_32;
3889 opengl_device_caps.dwDeviceZBufferBitDepth = DDBD_16|DDBD_24|DDBD_32;
3890 opengl_device_caps.dwMinTextureWidth = 1;
3891 opengl_device_caps.dwMinTextureHeight = 1;
3892 opengl_device_caps.dwMaxTextureWidth = 1024;
3893 opengl_device_caps.dwMaxTextureHeight = 1024;
3894 opengl_device_caps.dwMaxTextureRepeat = 16;
3895 opengl_device_caps.dwMaxTextureAspectRatio = 1024;
3896 opengl_device_caps.dwMaxAnisotropy = 0;
3897 opengl_device_caps.dvGuardBandLeft = 0.0;
3898 opengl_device_caps.dvGuardBandRight = 0.0;
3899 opengl_device_caps.dvGuardBandTop = 0.0;
3900 opengl_device_caps.dvGuardBandBottom = 0.0;
3901 opengl_device_caps.dvExtentsAdjust = 0.0;
3902 opengl_device_caps.dwStencilCaps = D3DSTENCILCAPS_DECRSAT | D3DSTENCILCAPS_INCRSAT | D3DSTENCILCAPS_INVERT | D3DSTENCILCAPS_KEEP |
3903 D3DSTENCILCAPS_REPLACE | D3DSTENCILCAPS_ZERO;
3904 opengl_device_caps.dwTextureOpCaps = D3DTEXOPCAPS_DISABLE | D3DTEXOPCAPS_SELECTARG1 | D3DTEXOPCAPS_SELECTARG2 | D3DTEXOPCAPS_MODULATE4X |
3905 D3DTEXOPCAPS_MODULATE2X | D3DTEXOPCAPS_MODULATE | D3DTEXOPCAPS_ADD | D3DTEXOPCAPS_ADDSIGNED2X | D3DTEXOPCAPS_ADDSIGNED |
3906 D3DTEXOPCAPS_BLENDDIFFUSEALPHA | D3DTEXOPCAPS_BLENDTEXTUREALPHA | D3DTEXOPCAPS_BLENDFACTORALPHA | D3DTEXOPCAPS_BLENDCURRENTALPHA;
3907 if (GL_extensions.max_texture_units != 0) {
3908 opengl_device_caps.wMaxTextureBlendStages = GL_extensions.max_texture_units;
3909 opengl_device_caps.wMaxSimultaneousTextures = GL_extensions.max_texture_units;
3910 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | GL_extensions.max_texture_units;
3912 opengl_device_caps.wMaxTextureBlendStages = 1;
3913 opengl_device_caps.wMaxSimultaneousTextures = 1;
3914 opengl_device_caps.dwFVFCaps = D3DFVFCAPS_DONOTSTRIPELEMENTS | 1;
3916 opengl_device_caps.dwMaxActiveLights = 16;
3917 opengl_device_caps.dvMaxVertexW = 100000000.0; /* No idea exactly what to put here... */
3918 opengl_device_caps.deviceGUID = IID_IDirect3DTnLHalDevice;
3919 opengl_device_caps.wMaxUserClipPlanes = 1;
3920 opengl_device_caps.wMaxVertexBlendMatrices = 0;
3921 opengl_device_caps.dwVertexProcessingCaps = D3DVTXPCAPS_TEXGEN | D3DVTXPCAPS_MATERIALSOURCE7 | D3DVTXPCAPS_VERTEXFOG |
3922 D3DVTXPCAPS_DIRECTIONALLIGHTS | D3DVTXPCAPS_POSITIONALLIGHTS | D3DVTXPCAPS_LOCALVIEWER;
3923 opengl_device_caps.dwReserved1 = 0;
3924 opengl_device_caps.dwReserved2 = 0;
3925 opengl_device_caps.dwReserved3 = 0;
3926 opengl_device_caps.dwReserved4 = 0;
3928 /* And now some GL overides :-) */
3929 glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &opengl_device_caps.dwMaxTextureWidth);
3930 opengl_device_caps.dwMaxTextureHeight = opengl_device_caps.dwMaxTextureWidth;
3931 opengl_device_caps.dwMaxTextureAspectRatio = opengl_device_caps.dwMaxTextureWidth;
3932 TRACE(": max texture size = %ld\n", opengl_device_caps.dwMaxTextureWidth);
3934 glGetIntegerv(GL_MAX_LIGHTS, (GLint *) &opengl_device_caps.dwMaxActiveLights);
3935 TRACE(": max active lights = %ld\n", opengl_device_caps.dwMaxActiveLights);
3937 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
3938 opengl_device_caps.wMaxUserClipPlanes = max_clip_planes;
3939 TRACE(": max clipping planes = %d\n", opengl_device_caps.wMaxUserClipPlanes);
3943 d3ddevice_init_at_startup(void *gl_handle)
3945 XVisualInfo template;
3950 Drawable drawable = (Drawable) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
3951 XWindowAttributes win_attr;
3952 GLXContext gl_context;
3954 const char *glExtensions;
3955 const char *glVersion;
3956 const char *glXExtensions = NULL;
3957 const void *(*pglXGetProcAddressARB)(const GLubyte *) = NULL;
3958 int major, minor, patch;
3960 TRACE("Initializing GL...\n");
3962 /* Get a default rendering context to have the 'caps' function query some info from GL */
3963 device_context = GetDC(0);
3964 display = get_display(device_context);
3965 ReleaseDC(0, device_context);
3968 if (XGetWindowAttributes(display, drawable, &win_attr)) {
3969 visual = win_attr.visual;
3971 visual = DefaultVisual(display, DefaultScreen(display));
3973 template.visualid = XVisualIDFromVisual(visual);
3974 vis = XGetVisualInfo(display, VisualIDMask, &template, &num);
3977 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
3980 gl_context = glXCreateContext(display, vis, NULL, GL_TRUE);
3982 if (gl_context == NULL) {
3984 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
3987 if (glXMakeCurrent(display, drawable, gl_context) == False) {
3988 glXDestroyContext(display, gl_context);
3990 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
3994 /* Then, query all extensions */
3995 glXExtensions = glXQueryExtensionsString(display, DefaultScreen(display));
3996 glExtensions = (const char *) glGetString(GL_EXTENSIONS);
3997 glVersion = (const char *) glGetString(GL_VERSION);
3998 if ((glXExtensions != NULL) && (gl_handle != NULL) && (strstr(glXExtensions, "GLX_ARB_get_proc_address"))) {
3999 pglXGetProcAddressARB = wine_dlsym(gl_handle, "glXGetProcAddressARB", NULL, 0);
4002 /* Parse the GL version string */
4003 sscanf(glVersion, "%d.%d.%d", &major, &minor, &patch);
4004 TRACE("GL version %d.%d.%d\n", major, minor, patch);
4006 /* And starts to fill the extension context properly */
4007 memset(&GL_extensions, 0, sizeof(GL_extensions));
4008 TRACE("GL supports following extensions used by Wine :\n");
4010 /* Mirrored Repeat extension :
4011 - GL_ARB_texture_mirrored_repeat
4012 - GL_IBM_texture_mirrored_repeat
4015 if ((strstr(glExtensions, "GL_ARB_texture_mirrored_repeat")) ||
4016 (strstr(glExtensions, "GL_IBM_texture_mirrored_repeat")) ||
4018 ((major == 1) && (minor >= 4))) {
4019 TRACE(" - mirrored repeat\n");
4020 GL_extensions.mirrored_repeat = TRUE;
4023 /* Texture LOD Bias :
4024 - GL_EXT_texture_lod_bias
4026 if (strstr(glExtensions, "GL_EXT_texture_lod_bias")) {
4027 TRACE(" - texture lod bias\n");
4028 GL_extensions.mipmap_lodbias = TRUE;
4031 /* For all subsequent extensions, we need glXGetProcAddress */
4032 if (pglXGetProcAddressARB != NULL) {
4033 /* Multi-texturing :
4034 - GL_ARB_multitexture
4037 if ((strstr(glExtensions, "GL_ARB_multitexture")) ||
4039 ((major == 1) && (minor > 2)) ||
4040 ((major == 1) && (minor == 2) && (patch >= 1))) {
4041 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE, &(GL_extensions.max_texture_units));
4042 TRACE(" - multi-texturing (%d stages)\n", GL_extensions.max_texture_units);
4043 /* We query the ARB version to be the most portable we can... */
4044 GL_extensions.glActiveTexture = pglXGetProcAddressARB("glActiveTextureARB");
4045 GL_extensions.glMultiTexCoord2fv = pglXGetProcAddressARB("glMultiTexCoord2fv");
4049 /* Fill the D3D capabilities according to what GL tells us... */
4052 /* And frees this now-useless context */
4053 glXMakeCurrent(display, None, NULL);
4054 glXDestroyContext(display, gl_context);