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 char interface_name
[] = "WINE Reference Direct3DX using OpenGL";
397 TRACE(" enumerating OpenGL D3DDevice interface using reference IID (IID %s).\n", debugstr_guid(&IID_IDirect3DRefDevice
));
400 ret_value
= cb((LPIID
) &IID_IDirect3DRefDevice
, interface_name
, device_name
, &d1
, &d2
, context
);
401 if (ret_value
!= D3DENUMRET_OK
)
406 char interface_name
[] = "WINE Direct3DX using OpenGL";
407 TRACE(" enumerating OpenGL D3DDevice interface (IID %s).\n", debugstr_guid(&IID_D3DDEVICE_OpenGL
));
410 ret_value
= cb((LPIID
) &IID_D3DDEVICE_OpenGL
, interface_name
, device_name
, &d1
, &d2
, context
);
411 if (ret_value
!= D3DENUMRET_OK
)
415 return D3DENUMRET_OK
;
418 HRESULT
d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb
, LPVOID context
)
420 D3DDEVICEDESC7 ddesc
;
421 char interface_name
[] = "WINE Direct3D7 using OpenGL";
422 char device_name
[] = "Wine D3D7 device";
424 fill_opengl_caps_7(&ddesc
);
426 TRACE(" enumerating OpenGL D3DDevice7 interface.\n");
428 return cb(interface_name
, device_name
, &ddesc
, context
);
432 GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release(LPDIRECT3DDEVICE7 iface
)
434 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
435 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
437 TRACE("(%p/%p)->() decrementing from %lu.\n", This
, iface
, This
->ref
);
438 if (!--(This
->ref
)) {
440 IDirectDrawSurfaceImpl
*surface
= This
->surface
, *surf
;
442 /* Release texture associated with the device */
443 for (i
= 0; i
< MAX_TEXTURES
; i
++) {
444 if (This
->current_texture
[i
] != NULL
)
445 IDirectDrawSurface7_Release(ICOM_INTERFACE(This
->current_texture
[i
], IDirectDrawSurface7
));
446 HeapFree(GetProcessHeap(), 0, This
->tex_mat
[i
]);
449 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
450 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
451 if ((surf
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) == (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) {
452 surf
->aux_ctx
= NULL
;
453 surf
->aux_data
= NULL
;
454 surf
->aux_flip
= NULL
;
458 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
459 IDirectDrawSurfaceImpl
*surf2
;
460 for (surf2
= surf
; surf2
->prev_attached
!= NULL
; surf2
= surf2
->prev_attached
) ;
461 for (; surf2
!= NULL
; surf2
= surf2
->next_attached
) {
462 if (((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_3DDEVICE
)) == (DDSCAPS_3DDEVICE
)) &&
463 ((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_ZBUFFER
)) != (DDSCAPS_ZBUFFER
))) {
464 /* Override the Lock / Unlock function for all these surfaces */
465 surf2
->lock_update
= surf2
->lock_update_prev
;
466 surf2
->unlock_update
= surf2
->unlock_update_prev
;
467 /* And install also the blt / bltfast overrides */
468 surf2
->aux_blt
= NULL
;
469 surf2
->aux_bltfast
= NULL
;
471 surf2
->d3ddevice
= NULL
;
475 /* And warn the D3D object that this device is no longer active... */
476 This
->d3d
->d3d_removed_device(This
->d3d
, This
);
478 HeapFree(GetProcessHeap(), 0, This
->world_mat
);
479 HeapFree(GetProcessHeap(), 0, This
->view_mat
);
480 HeapFree(GetProcessHeap(), 0, This
->proj_mat
);
482 if (glThis
->surface_ptr
)
483 HeapFree(GetProcessHeap(), 0, glThis
->surface_ptr
);
485 DeleteCriticalSection(&(This
->crit
));
488 if (glThis
->unlock_tex
)
489 glDeleteTextures(1, &(glThis
->unlock_tex
));
490 glXDestroyContext(glThis
->display
, glThis
->gl_context
);
492 HeapFree(GetProcessHeap(), 0, This
->clipping_planes
);
494 HeapFree(GetProcessHeap(), 0, This
);
501 GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps(LPDIRECT3DDEVICE3 iface
,
502 LPD3DDEVICEDESC lpD3DHWDevDesc
,
503 LPD3DDEVICEDESC lpD3DHELDevDesc
)
505 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
509 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DHWDevDesc
, lpD3DHELDevDesc
);
511 fill_opengl_caps(&desc
);
512 dwSize
= lpD3DHWDevDesc
->dwSize
;
513 memset(lpD3DHWDevDesc
, 0, dwSize
);
514 memcpy(lpD3DHWDevDesc
, &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
516 dwSize
= lpD3DHELDevDesc
->dwSize
;
517 memset(lpD3DHELDevDesc
, 0, dwSize
);
518 memcpy(lpD3DHELDevDesc
, &desc
, (dwSize
<= desc
.dwSize
? dwSize
: desc
.dwSize
));
520 TRACE(" returning caps : (no dump function yet)\n");
525 static HRESULT
enum_texture_format_OpenGL(LPD3DENUMTEXTUREFORMATSCALLBACK cb_1
,
526 LPD3DENUMPIXELFORMATSCALLBACK cb_2
,
530 LPDDPIXELFORMAT pformat
;
532 /* Do the texture enumeration */
533 sdesc
.dwSize
= sizeof(DDSURFACEDESC
);
534 sdesc
.dwFlags
= DDSD_PIXELFORMAT
| DDSD_CAPS
;
535 sdesc
.ddsCaps
.dwCaps
= DDSCAPS_TEXTURE
;
536 pformat
= &(sdesc
.ddpfPixelFormat
);
537 pformat
->dwSize
= sizeof(DDPIXELFORMAT
);
538 pformat
->dwFourCC
= 0;
540 TRACE("Enumerating GL_RGBA unpacked (32)\n");
541 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
542 pformat
->u1
.dwRGBBitCount
= 32;
543 pformat
->u2
.dwRBitMask
= 0x00FF0000;
544 pformat
->u3
.dwGBitMask
= 0x0000FF00;
545 pformat
->u4
.dwBBitMask
= 0x000000FF;
546 pformat
->u5
.dwRGBAlphaBitMask
= 0xFF000000;
547 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
548 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
550 TRACE("Enumerating GL_RGB unpacked (32)\n");
551 pformat
->dwFlags
= DDPF_RGB
;
552 pformat
->u1
.dwRGBBitCount
= 32;
553 pformat
->u2
.dwRBitMask
= 0x00FF0000;
554 pformat
->u3
.dwGBitMask
= 0x0000FF00;
555 pformat
->u4
.dwBBitMask
= 0x000000FF;
556 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
557 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
558 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
560 TRACE("Enumerating GL_RGB unpacked (24)\n");
561 pformat
->dwFlags
= DDPF_RGB
;
562 pformat
->u1
.dwRGBBitCount
= 24;
563 pformat
->u2
.dwRBitMask
= 0x00FF0000;
564 pformat
->u3
.dwGBitMask
= 0x0000FF00;
565 pformat
->u4
.dwBBitMask
= 0x000000FF;
566 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
567 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
568 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
570 /* Note : even if this is an 'emulated' texture format, it needs to be first
571 as some dumb applications seem to rely on that. */
572 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_1_5_5_5 (ARGB) (16)\n");
573 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
574 pformat
->u1
.dwRGBBitCount
= 16;
575 pformat
->u2
.dwRBitMask
= 0x00007C00;
576 pformat
->u3
.dwGBitMask
= 0x000003E0;
577 pformat
->u4
.dwBBitMask
= 0x0000001F;
578 pformat
->u5
.dwRGBAlphaBitMask
= 0x00008000;
579 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
580 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
582 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (ARGB) (16)\n");
583 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
584 pformat
->u1
.dwRGBBitCount
= 16;
585 pformat
->u2
.dwRBitMask
= 0x00000F00;
586 pformat
->u3
.dwGBitMask
= 0x000000F0;
587 pformat
->u4
.dwBBitMask
= 0x0000000F;
588 pformat
->u5
.dwRGBAlphaBitMask
= 0x0000F000;
589 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
590 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
592 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_6_5 (16)\n");
593 pformat
->dwFlags
= DDPF_RGB
;
594 pformat
->u1
.dwRGBBitCount
= 16;
595 pformat
->u2
.dwRBitMask
= 0x0000F800;
596 pformat
->u3
.dwGBitMask
= 0x000007E0;
597 pformat
->u4
.dwBBitMask
= 0x0000001F;
598 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
599 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
600 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
602 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_SHORT_5_5_5 (16)\n");
603 pformat
->dwFlags
= DDPF_RGB
;
604 pformat
->u1
.dwRGBBitCount
= 16;
605 pformat
->u2
.dwRBitMask
= 0x00007C00;
606 pformat
->u3
.dwGBitMask
= 0x000003E0;
607 pformat
->u4
.dwBBitMask
= 0x0000001F;
608 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
609 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
610 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
613 /* This is a compromise : some games choose the first 16 bit texture format with alpha they
614 find enumerated, others the last one. And both want to have the ARGB one.
616 So basically, forget our OpenGL roots and do not even enumerate our RGBA ones.
618 /* See argument about the RGBA format for 'packed' texture formats */
619 TRACE("Enumerating GL_RGBA unpacked (32)\n");
620 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
621 pformat
->u1
.dwRGBBitCount
= 32;
622 pformat
->u2
.dwRBitMask
= 0xFF000000;
623 pformat
->u3
.dwGBitMask
= 0x00FF0000;
624 pformat
->u4
.dwBBitMask
= 0x0000FF00;
625 pformat
->u5
.dwRGBAlphaBitMask
= 0x000000FF;
626 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
627 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
629 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_4_4_4_4 (16)\n");
630 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
631 pformat
->u1
.dwRGBBitCount
= 16;
632 pformat
->u2
.dwRBitMask
= 0x0000F000;
633 pformat
->u3
.dwGBitMask
= 0x00000F00;
634 pformat
->u4
.dwBBitMask
= 0x000000F0;
635 pformat
->u5
.dwRGBAlphaBitMask
= 0x0000000F;
636 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
637 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
639 TRACE("Enumerating GL_RGBA packed GL_UNSIGNED_SHORT_5_5_5_1 (16)\n");
640 pformat
->dwFlags
= DDPF_RGB
| DDPF_ALPHAPIXELS
;
641 pformat
->u1
.dwRGBBitCount
= 16;
642 pformat
->u2
.dwRBitMask
= 0x0000F800;
643 pformat
->u3
.dwGBitMask
= 0x000007C0;
644 pformat
->u4
.dwBBitMask
= 0x0000003E;
645 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000001;
646 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
647 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
650 TRACE("Enumerating GL_RGB packed GL_UNSIGNED_BYTE_3_3_2 (8)\n");
651 pformat
->dwFlags
= DDPF_RGB
;
652 pformat
->u1
.dwRGBBitCount
= 8;
653 pformat
->u2
.dwRBitMask
= 0x000000E0;
654 pformat
->u3
.dwGBitMask
= 0x0000001C;
655 pformat
->u4
.dwBBitMask
= 0x00000003;
656 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
657 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
658 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
660 TRACE("Enumerating Paletted (8)\n");
661 pformat
->dwFlags
= DDPF_PALETTEINDEXED8
;
662 pformat
->u1
.dwRGBBitCount
= 8;
663 pformat
->u2
.dwRBitMask
= 0x00000000;
664 pformat
->u3
.dwGBitMask
= 0x00000000;
665 pformat
->u4
.dwBBitMask
= 0x00000000;
666 pformat
->u5
.dwRGBAlphaBitMask
= 0x00000000;
667 if (cb_1
) if (cb_1(&sdesc
, context
) == 0) return DD_OK
;
668 if (cb_2
) if (cb_2(pformat
, context
) == 0) return DD_OK
;
670 TRACE("End of enumeration\n");
676 d3ddevice_find(IDirectDrawImpl
*d3d
,
677 LPD3DFINDDEVICESEARCH lpD3DDFS
,
678 LPD3DFINDDEVICERESULT lplpD3DDevice
)
682 if ((lpD3DDFS
->dwFlags
& D3DFDS_COLORMODEL
) &&
683 (lpD3DDFS
->dcmColorModel
!= D3DCOLOR_RGB
)) {
684 TRACE(" trying to request a non-RGB D3D color model. Not supported.\n");
685 return DDERR_INVALIDPARAMS
; /* No real idea what to return here :-) */
687 if (lpD3DDFS
->dwFlags
& D3DFDS_GUID
) {
688 TRACE(" trying to match guid %s.\n", debugstr_guid(&(lpD3DDFS
->guid
)));
689 if ((IsEqualGUID(&IID_D3DDEVICE_OpenGL
, &(lpD3DDFS
->guid
)) == 0) &&
690 (IsEqualGUID(&IID_IDirect3DHALDevice
, &(lpD3DDFS
->guid
)) == 0) &&
691 (IsEqualGUID(&IID_IDirect3DRefDevice
, &(lpD3DDFS
->guid
)) == 0)) {
692 TRACE(" no match for this GUID.\n");
693 return DDERR_INVALIDPARAMS
;
697 /* Now return our own GUID */
698 lplpD3DDevice
->guid
= IID_D3DDEVICE_OpenGL
;
699 fill_opengl_caps(&desc
);
700 lplpD3DDevice
->ddHwDesc
= desc
;
701 lplpD3DDevice
->ddSwDesc
= desc
;
703 TRACE(" returning Wine's OpenGL device with (undumped) capabilities\n");
709 GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats(LPDIRECT3DDEVICE2 iface
,
710 LPD3DENUMTEXTUREFORMATSCALLBACK lpD3DEnumTextureProc
,
713 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
714 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DEnumTextureProc
, lpArg
);
715 return enum_texture_format_OpenGL(lpD3DEnumTextureProc
, NULL
, lpArg
);
719 GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats(LPDIRECT3DDEVICE7 iface
,
720 LPD3DENUMPIXELFORMATSCALLBACK lpD3DEnumPixelProc
,
723 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
724 TRACE("(%p/%p)->(%p,%p)\n", This
, iface
, lpD3DEnumPixelProc
, lpArg
);
725 return enum_texture_format_OpenGL(NULL
, lpD3DEnumPixelProc
, lpArg
);
729 GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState(LPDIRECT3DDEVICE7 iface
,
730 D3DRENDERSTATETYPE dwRenderStateType
,
733 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
734 TRACE("(%p/%p)->(%08x,%08lx)\n", This
, iface
, dwRenderStateType
, dwRenderState
);
736 /* Call the render state functions */
737 store_render_state(This
, dwRenderStateType
, dwRenderState
, &This
->state_block
);
738 set_render_state(This
, dwRenderStateType
, &This
->state_block
);
744 GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState(LPDIRECT3DDEVICE7 iface
,
745 D3DRENDERSTATETYPE dwRenderStateType
,
746 LPDWORD lpdwRenderState
)
748 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
749 TRACE("(%p/%p)->(%08x,%p)\n", This
, iface
, dwRenderStateType
, lpdwRenderState
);
751 /* Call the render state functions */
752 get_render_state(This
, dwRenderStateType
, lpdwRenderState
, &This
->state_block
);
754 TRACE(" - asked for rendering state : %s, returning value %08lx.\n", _get_renderstate(dwRenderStateType
), *lpdwRenderState
);
760 GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface
,
761 D3DLIGHTSTATETYPE dwLightStateType
,
764 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice3
, iface
);
766 TRACE("(%p/%p)->(%08x,%08lx)\n", This
, iface
, dwLightStateType
, dwLightState
);
768 if (!dwLightStateType
&& (dwLightStateType
> D3DLIGHTSTATE_COLORVERTEX
)) {
769 TRACE("Unexpected Light State Type\n");
770 return DDERR_INVALIDPARAMS
;
773 if (dwLightStateType
== D3DLIGHTSTATE_MATERIAL
/* 1 */) {
774 IDirect3DMaterialImpl
*mat
= (IDirect3DMaterialImpl
*) dwLightState
;
777 TRACE(" activating material %p.\n", mat
);
780 ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
781 return DDERR_INVALIDPARAMS
;
783 } else if (dwLightStateType
== D3DLIGHTSTATE_COLORMODEL
/* 3 */) {
784 switch (dwLightState
) {
786 ERR("DDCOLOR_MONO should not happen!\n");
789 /* We are already in this mode */
790 TRACE("Setting color model to RGB (no-op).\n");
793 ERR("Unknown color model!\n");
794 return DDERR_INVALIDPARAMS
;
797 D3DRENDERSTATETYPE rs
;
798 switch (dwLightStateType
) {
799 case D3DLIGHTSTATE_AMBIENT
: /* 2 */
800 rs
= D3DRENDERSTATE_AMBIENT
;
802 case D3DLIGHTSTATE_FOGMODE
: /* 4 */
803 rs
= D3DRENDERSTATE_FOGVERTEXMODE
;
805 case D3DLIGHTSTATE_FOGSTART
: /* 5 */
806 rs
= D3DRENDERSTATE_FOGSTART
;
808 case D3DLIGHTSTATE_FOGEND
: /* 6 */
809 rs
= D3DRENDERSTATE_FOGEND
;
811 case D3DLIGHTSTATE_FOGDENSITY
: /* 7 */
812 rs
= D3DRENDERSTATE_FOGDENSITY
;
814 case D3DLIGHTSTATE_COLORVERTEX
: /* 8 */
815 rs
= D3DRENDERSTATE_COLORVERTEX
;
818 ERR("Unknown D3DLIGHTSTATETYPE %d.\n", dwLightStateType
);
819 return DDERR_INVALIDPARAMS
;
822 IDirect3DDevice7_SetRenderState(ICOM_INTERFACE(This
, IDirect3DDevice7
),
829 static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt
)
832 case D3DPT_POINTLIST
:
833 TRACE("Start POINTS\n");
838 TRACE("Start LINES\n");
842 case D3DPT_LINESTRIP
:
843 TRACE("Start LINE_STRIP\n");
844 glBegin(GL_LINE_STRIP
);
847 case D3DPT_TRIANGLELIST
:
848 TRACE("Start TRIANGLES\n");
849 glBegin(GL_TRIANGLES
);
852 case D3DPT_TRIANGLESTRIP
:
853 TRACE("Start TRIANGLE_STRIP\n");
854 glBegin(GL_TRIANGLE_STRIP
);
857 case D3DPT_TRIANGLEFAN
:
858 TRACE("Start TRIANGLE_FAN\n");
859 glBegin(GL_TRIANGLE_FAN
);
863 FIXME("Unhandled primitive %08x\n", d3dpt
);
868 /* This function calculate the Z coordinate from Zproj */
869 static float ZfromZproj(IDirect3DDeviceImpl
*This
, D3DVALUE Zproj
)
872 /* Assume that X = Y = 0 and W = 1 */
873 a
= This
->proj_mat
->_33
;
874 b
= This
->proj_mat
->_34
;
875 c
= This
->proj_mat
->_43
;
876 d
= This
->proj_mat
->_44
;
877 /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d
878 * So in non homogenous coordinates we have Zproj = (a * Z + c) / (b * Z + d)
879 * And finally Z = (d * Zproj - c) / (a - b * Zproj)
881 return (d
*Zproj
- c
) / (a
- b
*Zproj
);
884 static void build_fog_table(BYTE
*fog_table
, DWORD fog_color
) {
887 TRACE(" rebuilding fog table (%06lx)...\n", fog_color
& 0x00FFFFFF);
889 for (i
= 0; i
< 3; i
++) {
890 BYTE fog_color_component
= (fog_color
>> (8 * i
)) & 0xFF;
892 for (elt
= 0; elt
< 0x10000; elt
++) {
893 /* We apply the fog transformation and cache the result */
894 DWORD fog_intensity
= elt
& 0xFF;
895 DWORD vertex_color
= (elt
>> 8) & 0xFF;
896 fog_table
[(i
* 0x10000) + elt
] = ((fog_intensity
* vertex_color
) + ((0xFF - fog_intensity
) * fog_color_component
)) / 0xFF;
901 static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl
*This
,
902 BOOLEAN vertex_transformed
,
903 BOOLEAN vertex_lit
) {
904 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
906 /* Puts GL in the correct lighting / transformation mode */
907 if ((vertex_transformed
== FALSE
) &&
908 (glThis
->transform_state
!= GL_TRANSFORM_NORMAL
)) {
909 /* Need to put the correct transformation again if we go from Transformed
910 vertices to non-transformed ones.
912 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
913 This
->world_mat
, This
->view_mat
, This
->proj_mat
);
914 glThis
->transform_state
= GL_TRANSFORM_NORMAL
;
916 } else if ((vertex_transformed
== TRUE
) &&
917 (glThis
->transform_state
!= GL_TRANSFORM_ORTHO
)) {
918 /* Set our orthographic projection */
919 if (glThis
->transform_state
!= GL_TRANSFORM_ORTHO
) {
920 glThis
->transform_state
= GL_TRANSFORM_ORTHO
;
921 d3ddevice_set_ortho(This
);
925 /* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
926 if no fogging state change occurred */
927 if (This
->state_block
.render_state
[D3DRENDERSTATE_FOGENABLE
- 1] == TRUE
) {
928 if (vertex_transformed
== TRUE
) {
929 if (glThis
->fogging
!= 0) {
933 /* Now check if our fog_table still corresponds to the current vertex color.
934 Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
935 if ((glThis
->fog_table
[0 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 0) & 0xFF)) ||
936 (glThis
->fog_table
[1 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 8) & 0xFF)) ||
937 (glThis
->fog_table
[2 * 0x10000 + 0x0000] != ((This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1] >> 16) & 0xFF))) {
938 /* We need to rebuild our fog table.... */
939 build_fog_table(glThis
->fog_table
, This
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1]);
942 if (This
->state_block
.render_state
[D3DRENDERSTATE_FOGTABLEMODE
- 1] != D3DFOG_NONE
) {
943 switch (This
->state_block
.render_state
[D3DRENDERSTATE_FOGTABLEMODE
- 1]) {
944 case D3DFOG_LINEAR
: glFogi(GL_FOG_MODE
, GL_LINEAR
); break;
945 case D3DFOG_EXP
: glFogi(GL_FOG_MODE
, GL_EXP
); break;
946 case D3DFOG_EXP2
: glFogi(GL_FOG_MODE
, GL_EXP2
); break;
948 if (vertex_lit
== FALSE
) {
949 glFogf(GL_FOG_START
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGSTART
- 1]);
950 glFogf(GL_FOG_END
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGEND
- 1]);
952 /* Special case of 'pixel fog' */
953 glFogf(GL_FOG_START
, ZfromZproj(This
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGSTART
- 1]));
954 glFogf(GL_FOG_END
, ZfromZproj(This
, *(float*)&This
->state_block
.render_state
[D3DRENDERSTATE_FOGEND
- 1]));
956 if (glThis
->fogging
== 0) {
961 if (glThis
->fogging
!= 0) {
968 if (glThis
->fogging
!= 0) {
974 /* Handle the 'no-normal' case */
975 if ((vertex_lit
== FALSE
) && (This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1] == TRUE
)) {
976 if (glThis
->lighting
== 0) {
977 glEnable(GL_LIGHTING
);
978 glThis
->lighting
= 1;
981 if (glThis
->lighting
!= 0) {
982 glDisable(GL_LIGHTING
);
983 glThis
->lighting
= 0;
987 /* Handle the code for pre-vertex material properties */
988 if (vertex_transformed
== FALSE
) {
989 if ((This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1] == TRUE
) &&
990 (This
->state_block
.render_state
[D3DRENDERSTATE_COLORVERTEX
- 1] == TRUE
)) {
991 if ((This
->state_block
.render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
992 (This
->state_block
.render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
993 (This
->state_block
.render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
) ||
994 (This
->state_block
.render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] != D3DMCS_MATERIAL
)) {
995 glEnable(GL_COLOR_MATERIAL
);
1002 inline static void draw_primitive(IDirect3DDeviceImpl
*This
, DWORD maxvert
, WORD
*index
,
1003 D3DVERTEXTYPE d3dvt
, D3DPRIMITIVETYPE d3dpt
, void *lpvertex
)
1005 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1008 case D3DVT_VERTEX
: {
1009 strided
.position
.lpvData
= &((D3DVERTEX
*) lpvertex
)->u1
.x
;
1010 strided
.position
.dwStride
= sizeof(D3DVERTEX
);
1011 strided
.normal
.lpvData
= &((D3DVERTEX
*) lpvertex
)->u4
.nx
;
1012 strided
.normal
.dwStride
= sizeof(D3DVERTEX
);
1013 strided
.textureCoords
[0].lpvData
= &((D3DVERTEX
*) lpvertex
)->u7
.tu
;
1014 strided
.textureCoords
[0].dwStride
= sizeof(D3DVERTEX
);
1015 draw_primitive_strided(This
, d3dpt
, D3DFVF_VERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
1018 case D3DVT_LVERTEX
: {
1019 strided
.position
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u1
.x
;
1020 strided
.position
.dwStride
= sizeof(D3DLVERTEX
);
1021 strided
.diffuse
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u4
.color
;
1022 strided
.diffuse
.dwStride
= sizeof(D3DLVERTEX
);
1023 strided
.specular
.lpvData
= &((D3DLVERTEX
*) lpvertex
)->u5
.specular
;
1024 strided
.specular
.dwStride
= sizeof(D3DLVERTEX
);
1025 strided
.textureCoords
[0].lpvData
= &((D3DLVERTEX
*) lpvertex
)->u6
.tu
;
1026 strided
.textureCoords
[0].dwStride
= sizeof(D3DLVERTEX
);
1027 draw_primitive_strided(This
, d3dpt
, D3DFVF_LVERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
1030 case D3DVT_TLVERTEX
: {
1031 strided
.position
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u1
.sx
;
1032 strided
.position
.dwStride
= sizeof(D3DTLVERTEX
);
1033 strided
.diffuse
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u5
.color
;
1034 strided
.diffuse
.dwStride
= sizeof(D3DTLVERTEX
);
1035 strided
.specular
.lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u6
.specular
;
1036 strided
.specular
.dwStride
= sizeof(D3DTLVERTEX
);
1037 strided
.textureCoords
[0].lpvData
= &((D3DTLVERTEX
*) lpvertex
)->u7
.tu
;
1038 strided
.textureCoords
[0].dwStride
= sizeof(D3DTLVERTEX
);
1039 draw_primitive_strided(This
, d3dpt
, D3DFVF_TLVERTEX
, &strided
, 0 /* Unused */, index
, maxvert
, 0 /* Unused */);
1043 FIXME("Unhandled vertex type %08x\n", d3dvt
);
1049 GL_IDirect3DDeviceImpl_2_DrawPrimitive(LPDIRECT3DDEVICE2 iface
,
1050 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1051 D3DVERTEXTYPE d3dvtVertexType
,
1053 DWORD dwVertexCount
,
1056 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
1058 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwFlags
);
1059 if (TRACE_ON(ddraw
)) {
1060 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1063 draw_primitive(This
, dwVertexCount
, NULL
, d3dvtVertexType
, d3dptPrimitiveType
, lpvVertices
);
1069 GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive(LPDIRECT3DDEVICE2 iface
,
1070 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1071 D3DVERTEXTYPE d3dvtVertexType
,
1073 DWORD dwVertexCount
,
1078 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice2
, iface
);
1079 TRACE("(%p/%p)->(%08x,%08x,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
1080 if (TRACE_ON(ddraw
)) {
1081 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1084 draw_primitive(This
, dwIndexCount
, dwIndices
, d3dvtVertexType
, d3dptPrimitiveType
, lpvVertices
);
1090 GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer(LPDIRECT3DDEVICE iface
,
1091 LPD3DEXECUTEBUFFERDESC lpDesc
,
1092 LPDIRECT3DEXECUTEBUFFER
* lplpDirect3DExecuteBuffer
,
1093 IUnknown
* pUnkOuter
)
1095 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice
, iface
);
1096 IDirect3DExecuteBufferImpl
*ret
;
1099 TRACE("(%p/%p)->(%p,%p,%p)\n", This
, iface
, lpDesc
, lplpDirect3DExecuteBuffer
, pUnkOuter
);
1101 ret_value
= d3dexecutebuffer_create(&ret
, This
->d3d
, This
, lpDesc
);
1102 *lplpDirect3DExecuteBuffer
= ICOM_INTERFACE(ret
, IDirect3DExecuteBuffer
);
1104 TRACE(" returning %p.\n", *lplpDirect3DExecuteBuffer
);
1109 static void flush_zbuffer_to_GL(IDirect3DDeviceImpl
*d3d_dev
, LPCRECT pRect
, IDirectDrawSurfaceImpl
*surf
) {
1110 static BOOLEAN first
= TRUE
;
1111 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
1115 if (first
== TRUE
) {
1116 MESSAGE("Warning : application does direct locking of ZBuffer - expect slowdowns on many GL implementations :-)\n");
1120 TRACE("flushing ZBuffer back to GL\n");
1122 if (gl_d3d_dev
->transform_state
!= GL_TRANSFORM_ORTHO
) {
1123 gl_d3d_dev
->transform_state
= GL_TRANSFORM_ORTHO
;
1124 d3ddevice_set_ortho(d3d_dev
);
1127 glMatrixMode(GL_MODELVIEW
);
1130 if (gl_d3d_dev
->depth_test
== 0) glEnable(GL_DEPTH_TEST
);
1131 if (d3d_dev
->state_block
.render_state
[D3DRENDERSTATE_ZFUNC
- 1] != D3DCMP_ALWAYS
) glDepthFunc(GL_ALWAYS
);
1132 glColorMask(GL_FALSE
, GL_FALSE
, GL_FALSE
, GL_FALSE
);
1134 /* This loop here is to prevent using PixelZoom that may be unoptimized for the 1.0 / -1.0 case
1137 switch (surf
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwZBufferBitDepth
) {
1138 case 16: type
= GL_UNSIGNED_SHORT
; break;
1139 case 32: type
= GL_UNSIGNED_INT
; break;
1140 default: FIXME("Unhandled ZBuffer format !\n"); goto restore_state
;
1143 for (row
= 0; row
< surf
->surface_desc
.dwHeight
; row
++) {
1144 /* glRasterPos3d(0.0, row + 1.0, 0.5); */
1145 glRasterPos2i(0, row
+ 1);
1146 glDrawPixels(surf
->surface_desc
.dwWidth
, 1, GL_DEPTH_COMPONENT
, type
,
1147 ((unsigned char *) surf
->surface_desc
.lpSurface
) + (row
* surf
->surface_desc
.u1
.lPitch
));
1151 glColorMask(GL_TRUE
, GL_TRUE
, GL_TRUE
, GL_TRUE
);
1152 if (d3d_dev
->state_block
.render_state
[D3DRENDERSTATE_ZFUNC
- 1] != D3DCMP_ALWAYS
)
1153 glDepthFunc(convert_D3D_compare_to_GL(d3d_dev
->state_block
.render_state
[D3DRENDERSTATE_ZFUNC
- 1]));
1154 if (gl_d3d_dev
->depth_test
== 0) glDisable(GL_DEPTH_TEST
);
1157 /* These are the various handler used in the generic path */
1158 inline static void handle_xyz(D3DVALUE
*coords
) {
1159 glVertex3fv(coords
);
1161 inline static void handle_xyzrhw(D3DVALUE
*coords
) {
1162 if (coords
[3] < 1e-8)
1163 glVertex3fv(coords
);
1165 GLfloat w
= 1.0 / coords
[3];
1167 glVertex4f(coords
[0] * w
,
1173 inline static void handle_normal(D3DVALUE
*coords
) {
1174 glNormal3fv(coords
);
1177 inline static void handle_diffuse_base(STATEBLOCK
*sb
, DWORD
*color
) {
1178 if ((sb
->render_state
[D3DRENDERSTATE_ALPHATESTENABLE
- 1] == TRUE
) ||
1179 (sb
->render_state
[D3DRENDERSTATE_ALPHABLENDENABLE
- 1] == TRUE
)) {
1180 glColor4ub((*color
>> 16) & 0xFF,
1181 (*color
>> 8) & 0xFF,
1182 (*color
>> 0) & 0xFF,
1183 (*color
>> 24) & 0xFF);
1185 glColor3ub((*color
>> 16) & 0xFF,
1186 (*color
>> 8) & 0xFF,
1187 (*color
>> 0) & 0xFF);
1191 inline static void handle_specular_base(STATEBLOCK
*sb
, DWORD
*color
) {
1192 glColor4ub((*color
>> 16) & 0xFF,
1193 (*color
>> 8) & 0xFF,
1194 (*color
>> 0) & 0xFF,
1195 (*color
>> 24) & 0xFF); /* No idea if the alpha field is really used.. */
1198 inline static void handle_diffuse(STATEBLOCK
*sb
, DWORD
*color
, BOOLEAN lighted
) {
1199 if ((lighted
== FALSE
) &&
1200 (sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1] == TRUE
) &&
1201 (sb
->render_state
[D3DRENDERSTATE_COLORVERTEX
- 1] == TRUE
)) {
1202 if (sb
->render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1203 glColorMaterial(GL_FRONT_AND_BACK
, GL_DIFFUSE
);
1204 handle_diffuse_base(sb
, color
);
1206 if (sb
->render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1207 glColorMaterial(GL_FRONT_AND_BACK
, GL_AMBIENT
);
1208 handle_diffuse_base(sb
, color
);
1210 if ((sb
->render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) &&
1211 (sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1] == TRUE
)) {
1212 glColorMaterial(GL_FRONT_AND_BACK
, GL_SPECULAR
);
1213 handle_diffuse_base(sb
, color
);
1215 if (sb
->render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] == D3DMCS_COLOR1
) {
1216 glColorMaterial(GL_FRONT_AND_BACK
, GL_EMISSION
);
1217 handle_diffuse_base(sb
, color
);
1220 handle_diffuse_base(sb
, color
);
1224 inline static void handle_specular(STATEBLOCK
*sb
, DWORD
*color
, BOOLEAN lighted
) {
1225 if ((lighted
== FALSE
) &&
1226 (sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1] == TRUE
) &&
1227 (sb
->render_state
[D3DRENDERSTATE_COLORVERTEX
- 1] == TRUE
)) {
1228 if (sb
->render_state
[D3DRENDERSTATE_DIFFUSEMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1229 glColorMaterial(GL_FRONT_AND_BACK
, GL_DIFFUSE
);
1230 handle_specular_base(sb
, color
);
1232 if (sb
->render_state
[D3DRENDERSTATE_AMBIENTMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1233 glColorMaterial(GL_FRONT_AND_BACK
, GL_AMBIENT
);
1234 handle_specular_base(sb
, color
);
1236 if ((sb
->render_state
[D3DRENDERSTATE_SPECULARMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) &&
1237 (sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1] == TRUE
)) {
1238 glColorMaterial(GL_FRONT_AND_BACK
, GL_SPECULAR
);
1239 handle_specular_base(sb
, color
);
1241 if (sb
->render_state
[D3DRENDERSTATE_EMISSIVEMATERIALSOURCE
- 1] == D3DMCS_COLOR2
) {
1242 glColorMaterial(GL_FRONT_AND_BACK
, GL_EMISSION
);
1243 handle_specular_base(sb
, color
);
1246 /* No else here as we do not know how to handle 'specular' on its own in any case.. */
1249 inline static void handle_diffuse_and_specular(STATEBLOCK
*sb
, BYTE
*fog_table
, DWORD
*color_d
, DWORD
*color_s
, BOOLEAN lighted
) {
1250 if (lighted
== TRUE
) {
1251 DWORD color
= *color_d
;
1252 if (sb
->render_state
[D3DRENDERSTATE_FOGENABLE
- 1] == TRUE
) {
1253 /* Special case where the specular value is used to do fogging */
1254 BYTE fog_intensity
= *color_s
>> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
1255 color
&= 0xFF000000; /* Only keep the alpha component */
1256 color
|= fog_table
[((*color_d
>> 0) & 0xFF) << 8 | fog_intensity
] << 0;
1257 color
|= fog_table
[((*color_d
>> 8) & 0xFF) << 8 | fog_intensity
] << 8;
1258 color
|= fog_table
[((*color_d
>> 16) & 0xFF) << 8 | fog_intensity
] << 16;
1260 if (sb
->render_state
[D3DRENDERSTATE_SPECULARENABLE
- 1] == TRUE
) {
1261 /* Standard specular value in transformed mode. TODO */
1263 handle_diffuse_base(sb
, &color
);
1265 if (sb
->render_state
[D3DRENDERSTATE_LIGHTING
- 1] == TRUE
) {
1266 handle_diffuse(sb
, color_d
, FALSE
);
1267 handle_specular(sb
, color_s
, FALSE
);
1269 /* In that case, only put the diffuse color... */
1270 handle_diffuse_base(sb
, color_d
);
1275 inline static void handle_texture(D3DVALUE
*coords
) {
1276 glTexCoord2fv(coords
);
1278 inline static void handle_textures(D3DVALUE
*coords
, int tex_stage
) {
1279 if (GL_extensions
.glMultiTexCoord2fv
) {
1280 GL_extensions
.glMultiTexCoord2fv(GL_TEXTURE0_WINE
+ tex_stage
, coords
);
1282 if (tex_stage
== 0) glTexCoord2fv(coords
);
1286 static void draw_primitive_strided(IDirect3DDeviceImpl
*This
,
1287 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1288 DWORD d3dvtVertexType
,
1289 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1290 DWORD dwVertexCount
,
1295 BOOLEAN vertex_lighted
= FALSE
;
1296 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
1297 int num_active_stages
= 0;
1299 /* I put the trace before the various locks... So as to better understand where locks occur :-) */
1300 if (TRACE_ON(ddraw
)) {
1301 TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType
);
1304 /* This is to prevent 'thread contention' between a thread locking the device and another
1305 doing 3D display on it... */
1306 EnterCriticalSection(&(This
->crit
));
1309 if (glThis
->state
[WINE_GL_BUFFER_BACK
] == SURFACE_MEMORY_DIRTY
) {
1310 This
->flush_to_framebuffer(This
, &(glThis
->lock_rect
[WINE_GL_BUFFER_BACK
]), glThis
->lock_surf
[WINE_GL_BUFFER_BACK
]);
1312 glThis
->state
[WINE_GL_BUFFER_BACK
] = SURFACE_GL
;
1314 if (This
->current_zbuffer
== NULL
) {
1315 /* Search for an attached ZBuffer */
1316 static const DDSCAPS2 zbuf_caps
= { DDSCAPS_ZBUFFER
, 0, 0, 0 };
1317 LPDIRECTDRAWSURFACE7 zbuf
;
1320 hr
= IDirectDrawSurface7_GetAttachedSurface(ICOM_INTERFACE(This
->surface
, IDirectDrawSurface7
),
1321 (DDSCAPS2
*) &zbuf_caps
, &zbuf
);
1323 This
->current_zbuffer
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, zbuf
);
1324 IDirectDrawSurface7_Release(zbuf
);
1327 if (This
->current_zbuffer
!= NULL
) {
1328 if (This
->current_zbuffer
->get_dirty_status(This
->current_zbuffer
, NULL
)) {
1329 flush_zbuffer_to_GL(This
, NULL
, This
->current_zbuffer
);
1333 if ( ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) != D3DFVF_XYZ
) ||
1334 ((d3dvtVertexType
& D3DFVF_NORMAL
) == 0) )
1335 vertex_lighted
= TRUE
;
1337 /* Compute the number of active texture stages and set the various texture parameters */
1338 num_active_stages
= draw_primitive_handle_textures(This
);
1340 /* And restore to handle '0' in the case we use glTexCorrd calls */
1341 if (glThis
->current_active_tex_unit
!= GL_TEXTURE0_WINE
) {
1342 GL_extensions
.glActiveTexture(GL_TEXTURE0_WINE
);
1343 glThis
->current_active_tex_unit
= GL_TEXTURE0_WINE
;
1346 draw_primitive_handle_GL_state(This
,
1347 (d3dvtVertexType
& D3DFVF_POSITION_MASK
) != D3DFVF_XYZ
,
1349 draw_primitive_start_GL(d3dptPrimitiveType
);
1351 /* Some fast paths first before the generic case.... */
1352 if ((d3dvtVertexType
== D3DFVF_VERTEX
) && (num_active_stages
<= 1)) {
1355 for (index
= 0; index
< dwIndexCount
; index
++) {
1356 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1358 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1359 D3DVALUE
*tex_coord
=
1360 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[0].lpvData
) + i
* lpD3DDrawPrimStrideData
->textureCoords
[0].dwStride
);
1361 D3DVALUE
*position
=
1362 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1364 handle_normal(normal
);
1365 handle_texture(tex_coord
);
1366 handle_xyz(position
);
1368 TRACE_(ddraw_geom
)(" %f %f %f / %f %f %f (%f %f)\n",
1369 position
[0], position
[1], position
[2],
1370 normal
[0], normal
[1], normal
[2],
1371 tex_coord
[0], tex_coord
[1]);
1373 } else if ((d3dvtVertexType
== D3DFVF_TLVERTEX
) && (num_active_stages
<= 1)) {
1376 for (index
= 0; index
< dwIndexCount
; index
++) {
1377 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1379 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1381 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1382 D3DVALUE
*tex_coord
=
1383 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[0].lpvData
) + i
* lpD3DDrawPrimStrideData
->textureCoords
[0].dwStride
);
1384 D3DVALUE
*position
=
1385 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1387 handle_diffuse_and_specular(&(This
->state_block
), glThis
->fog_table
, color_d
, color_s
, TRUE
);
1388 handle_texture(tex_coord
);
1389 handle_xyzrhw(position
);
1391 TRACE_(ddraw_geom
)(" %f %f %f %f / %02lx %02lx %02lx %02lx - %02lx %02lx %02lx %02lx (%f %f)\n",
1392 position
[0], position
[1], position
[2], position
[3],
1393 (*color_d
>> 16) & 0xFF,
1394 (*color_d
>> 8) & 0xFF,
1395 (*color_d
>> 0) & 0xFF,
1396 (*color_d
>> 24) & 0xFF,
1397 (*color_s
>> 16) & 0xFF,
1398 (*color_s
>> 8) & 0xFF,
1399 (*color_s
>> 0) & 0xFF,
1400 (*color_s
>> 24) & 0xFF,
1401 tex_coord
[0], tex_coord
[1]);
1403 } else if (((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) ||
1404 ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
)) {
1405 /* This is the 'slow path' but that should support all possible vertex formats out there...
1406 Note that people should write a fast path for all vertex formats out there...
1409 int num_tex_index
= ((d3dvtVertexType
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
);
1410 static const D3DVALUE no_index
[] = { 0.0, 0.0, 0.0, 0.0 };
1412 for (index
= 0; index
< dwIndexCount
; index
++) {
1413 int i
= (dwIndices
== NULL
) ? index
: dwIndices
[index
];
1416 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1418 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1419 handle_normal(normal
);
1421 if ((d3dvtVertexType
& (D3DFVF_DIFFUSE
|D3DFVF_SPECULAR
)) == (D3DFVF_DIFFUSE
|D3DFVF_SPECULAR
)) {
1423 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1425 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1426 handle_diffuse_and_specular(&(This
->state_block
), glThis
->fog_table
, color_d
, color_s
, vertex_lighted
);
1428 if (d3dvtVertexType
& D3DFVF_SPECULAR
) {
1430 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1431 handle_specular(&(This
->state_block
), color_s
, vertex_lighted
);
1432 } else if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1434 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1435 handle_diffuse(&(This
->state_block
), color_d
, vertex_lighted
);
1439 for (tex_stage
= 0; tex_stage
< num_active_stages
; tex_stage
++) {
1440 int tex_index
= This
->state_block
.texture_stage_state
[tex_stage
][D3DTSS_TEXCOORDINDEX
- 1] & 0x0000FFFF;
1441 if (tex_index
>= num_tex_index
) {
1442 handle_textures((D3DVALUE
*) no_index
, tex_stage
);
1444 D3DVALUE
*tex_coord
=
1445 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].lpvData
) +
1446 i
* lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].dwStride
);
1447 handle_textures(tex_coord
, tex_stage
);
1451 if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) {
1452 D3DVALUE
*position
=
1453 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1454 handle_xyz(position
);
1455 } else if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) {
1456 D3DVALUE
*position
=
1457 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1458 handle_xyzrhw(position
);
1461 if (TRACE_ON(ddraw_geom
)) {
1464 if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZ
) {
1465 D3DVALUE
*position
=
1466 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1467 TRACE_(ddraw_geom
)(" %f %f %f", position
[0], position
[1], position
[2]);
1468 } else if ((d3dvtVertexType
& D3DFVF_POSITION_MASK
) == D3DFVF_XYZRHW
) {
1469 D3DVALUE
*position
=
1470 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->position
.lpvData
) + i
* lpD3DDrawPrimStrideData
->position
.dwStride
);
1471 TRACE_(ddraw_geom
)(" %f %f %f %f", position
[0], position
[1], position
[2], position
[3]);
1473 if (d3dvtVertexType
& D3DFVF_NORMAL
) {
1475 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->normal
.lpvData
) + i
* lpD3DDrawPrimStrideData
->normal
.dwStride
);
1476 TRACE_(ddraw_geom
)(" / %f %f %f", normal
[0], normal
[1], normal
[2]);
1478 if (d3dvtVertexType
& D3DFVF_DIFFUSE
) {
1480 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->diffuse
.lpvData
) + i
* lpD3DDrawPrimStrideData
->diffuse
.dwStride
);
1481 TRACE_(ddraw_geom
)(" / %02lx %02lx %02lx %02lx",
1482 (*color_d
>> 16) & 0xFF,
1483 (*color_d
>> 8) & 0xFF,
1484 (*color_d
>> 0) & 0xFF,
1485 (*color_d
>> 24) & 0xFF);
1487 if (d3dvtVertexType
& D3DFVF_SPECULAR
) {
1489 (DWORD
*) (((char *) lpD3DDrawPrimStrideData
->specular
.lpvData
) + i
* lpD3DDrawPrimStrideData
->specular
.dwStride
);
1490 TRACE_(ddraw_geom
)(" / %02lx %02lx %02lx %02lx",
1491 (*color_s
>> 16) & 0xFF,
1492 (*color_s
>> 8) & 0xFF,
1493 (*color_s
>> 0) & 0xFF,
1494 (*color_s
>> 24) & 0xFF);
1496 for (tex_index
= 0; tex_index
< ((d3dvtVertexType
& D3DFVF_TEXCOUNT_MASK
) >> D3DFVF_TEXCOUNT_SHIFT
); tex_index
++) {
1497 D3DVALUE
*tex_coord
=
1498 (D3DVALUE
*) (((char *) lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].lpvData
) +
1499 i
* lpD3DDrawPrimStrideData
->textureCoords
[tex_index
].dwStride
);
1500 TRACE_(ddraw_geom
)(" / %f %f", tex_coord
[0], tex_coord
[1]);
1502 TRACE_(ddraw_geom
)("\n");
1506 ERR(" matrix weighting not handled yet....\n");
1511 /* Whatever the case, disable the color material stuff */
1512 glDisable(GL_COLOR_MATERIAL
);
1517 LeaveCriticalSection(&(This
->crit
));
1521 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive(LPDIRECT3DDEVICE7 iface
,
1522 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1523 DWORD d3dvtVertexType
,
1525 DWORD dwVertexCount
,
1528 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1529 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1531 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwFlags
);
1532 if (TRACE_ON(ddraw
)) {
1533 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1536 convert_FVF_to_strided_data(d3dvtVertexType
, lpvVertices
, &strided
, 0);
1537 draw_primitive_strided(This
, d3dptPrimitiveType
, d3dvtVertexType
, &strided
, dwVertexCount
, NULL
, dwVertexCount
, dwFlags
);
1543 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive(LPDIRECT3DDEVICE7 iface
,
1544 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1545 DWORD d3dvtVertexType
,
1547 DWORD dwVertexCount
,
1552 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1553 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1555 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, d3dvtVertexType
, lpvVertices
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
1556 if (TRACE_ON(ddraw
)) {
1557 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1560 convert_FVF_to_strided_data(d3dvtVertexType
, lpvVertices
, &strided
, 0);
1561 draw_primitive_strided(This
, d3dptPrimitiveType
, d3dvtVertexType
, &strided
, dwVertexCount
, dwIndices
, dwIndexCount
, dwFlags
);
1567 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided(LPDIRECT3DDEVICE7 iface
,
1568 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1570 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1571 DWORD dwVertexCount
,
1574 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1576 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, dwFlags
);
1577 if (TRACE_ON(ddraw
)) {
1578 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1580 draw_primitive_strided(This
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, NULL
, dwVertexCount
, dwFlags
);
1586 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided(LPDIRECT3DDEVICE7 iface
,
1587 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1589 LPD3DDRAWPRIMITIVESTRIDEDDATA lpD3DDrawPrimStrideData
,
1590 DWORD dwVertexCount
,
1595 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1597 TRACE("(%p/%p)->(%08x,%08lx,%p,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, lpIndex
, dwIndexCount
, dwFlags
);
1598 if (TRACE_ON(ddraw
)) {
1599 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1602 draw_primitive_strided(This
, d3dptPrimitiveType
, dwVertexType
, lpD3DDrawPrimStrideData
, dwVertexCount
, lpIndex
, dwIndexCount
, dwFlags
);
1608 GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB(LPDIRECT3DDEVICE7 iface
,
1609 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1610 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf
,
1611 DWORD dwStartVertex
,
1612 DWORD dwNumVertices
,
1615 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1616 IDirect3DVertexBufferImpl
*vb_impl
= ICOM_OBJECT(IDirect3DVertexBufferImpl
, IDirect3DVertexBuffer7
, lpD3DVertexBuf
);
1617 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1619 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, lpD3DVertexBuf
, dwStartVertex
, dwNumVertices
, dwFlags
);
1620 if (TRACE_ON(ddraw
)) {
1621 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1624 if (vb_impl
->processed
== TRUE
) {
1625 IDirect3DVertexBufferGLImpl
*vb_glimp
= (IDirect3DVertexBufferGLImpl
*) vb_impl
;
1626 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
1628 glThis
->transform_state
= GL_TRANSFORM_VERTEXBUFFER
;
1629 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
1630 &(vb_glimp
->world_mat
), &(vb_glimp
->view_mat
), &(vb_glimp
->proj_mat
));
1632 convert_FVF_to_strided_data(vb_glimp
->dwVertexTypeDesc
, vb_glimp
->vertices
, &strided
, dwStartVertex
);
1633 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_glimp
->dwVertexTypeDesc
, &strided
, dwNumVertices
, NULL
, dwNumVertices
, dwFlags
);
1636 convert_FVF_to_strided_data(vb_impl
->desc
.dwFVF
, vb_impl
->vertices
, &strided
, dwStartVertex
);
1637 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_impl
->desc
.dwFVF
, &strided
, dwNumVertices
, NULL
, dwNumVertices
, dwFlags
);
1644 GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface
,
1645 D3DPRIMITIVETYPE d3dptPrimitiveType
,
1646 LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf
,
1647 DWORD dwStartVertex
,
1648 DWORD dwNumVertices
,
1653 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1654 IDirect3DVertexBufferImpl
*vb_impl
= ICOM_OBJECT(IDirect3DVertexBufferImpl
, IDirect3DVertexBuffer7
, lpD3DVertexBuf
);
1655 D3DDRAWPRIMITIVESTRIDEDDATA strided
;
1657 TRACE("(%p/%p)->(%08x,%p,%08lx,%08lx,%p,%08lx,%08lx)\n", This
, iface
, d3dptPrimitiveType
, lpD3DVertexBuf
, dwStartVertex
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1658 if (TRACE_ON(ddraw
)) {
1659 TRACE(" - flags : "); dump_DPFLAGS(dwFlags
);
1662 if (vb_impl
->processed
== TRUE
) {
1663 IDirect3DVertexBufferGLImpl
*vb_glimp
= (IDirect3DVertexBufferGLImpl
*) vb_impl
;
1664 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
1666 glThis
->transform_state
= GL_TRANSFORM_VERTEXBUFFER
;
1667 This
->set_matrices(This
, VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
,
1668 &(vb_glimp
->world_mat
), &(vb_glimp
->view_mat
), &(vb_glimp
->proj_mat
));
1670 convert_FVF_to_strided_data(vb_glimp
->dwVertexTypeDesc
, vb_glimp
->vertices
, &strided
, dwStartVertex
);
1671 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_glimp
->dwVertexTypeDesc
, &strided
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1674 convert_FVF_to_strided_data(vb_impl
->desc
.dwFVF
, vb_impl
->vertices
, &strided
, dwStartVertex
);
1675 draw_primitive_strided(This
, d3dptPrimitiveType
, vb_impl
->desc
.dwFVF
, &strided
, dwNumVertices
, lpwIndices
, dwIndexCount
, dwFlags
);
1681 /* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
1683 handle_color_alpha_args(IDirect3DDeviceImpl
*This
, DWORD dwStage
, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType
, DWORD dwState
, D3DTEXTUREOP tex_op
)
1685 BOOLEAN is_complement
= FALSE
;
1686 BOOLEAN is_alpha_replicate
= FALSE
;
1687 BOOLEAN handled
= TRUE
;
1689 BOOLEAN is_color
= ((d3dTexStageStateType
== D3DTSS_COLORARG1
) || (d3dTexStageStateType
== D3DTSS_COLORARG2
));
1693 if (d3dTexStageStateType
== D3DTSS_COLORARG1
) num
= 0;
1694 else if (d3dTexStageStateType
== D3DTSS_COLORARG2
) num
= 1;
1699 if (tex_op
== D3DTOP_SELECTARG2
) {
1703 if (d3dTexStageStateType
== D3DTSS_ALPHAARG1
) num
= 0;
1704 else if (d3dTexStageStateType
== D3DTSS_ALPHAARG2
) num
= 1;
1709 if (tex_op
== D3DTOP_SELECTARG2
) {
1714 if (dwState
& D3DTA_COMPLEMENT
) {
1715 is_complement
= TRUE
;
1717 if (dwState
& D3DTA_ALPHAREPLICATE
) {
1718 is_alpha_replicate
= TRUE
;
1720 dwState
&= D3DTA_SELECTMASK
;
1721 if ((dwStage
== 0) && (dwState
== D3DTA_CURRENT
)) {
1722 dwState
= D3DTA_DIFFUSE
;
1726 case D3DTA_CURRENT
: src
= GL_PREVIOUS_EXT
; break;
1727 case D3DTA_DIFFUSE
: src
= GL_PRIMARY_COLOR_EXT
; break;
1728 case D3DTA_TEXTURE
: src
= GL_TEXTURE
; break;
1729 case D3DTA_TFACTOR
: {
1730 /* Get the constant value from the current rendering state */
1732 DWORD col
= This
->state_block
.render_state
[D3DRENDERSTATE_TEXTUREFACTOR
- 1];
1734 color
[0] = ((col
>> 16) & 0xFF) / 255.0f
;
1735 color
[1] = ((col
>> 8) & 0xFF) / 255.0f
;
1736 color
[2] = ((col
>> 0) & 0xFF) / 255.0f
;
1737 color
[3] = ((col
>> 24) & 0xFF) / 255.0f
;
1738 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
, color
);
1740 src
= GL_CONSTANT_EXT
;
1742 default: src
= GL_TEXTURE
; handled
= FALSE
; break;
1746 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB_EXT
+ num
, src
);
1747 if (is_alpha_replicate
) {
1748 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_ALPHA
: GL_SRC_ALPHA
);
1750 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_COLOR
: GL_SRC_COLOR
);
1753 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA_EXT
+ num
, src
);
1754 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA_EXT
+ num
, is_complement
? GL_ONE_MINUS_SRC_ALPHA
: GL_SRC_ALPHA
);
1761 GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface
,
1763 D3DTEXTURESTAGESTATETYPE d3dTexStageStateType
,
1766 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
1767 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
1772 TRACE("(%p/%p)->(%08lx,%08x,%08lx)\n", This
, iface
, dwStage
, d3dTexStageStateType
, dwState
);
1774 if (((GL_extensions
.max_texture_units
== 0) && (dwStage
> 0)) ||
1775 ((GL_extensions
.max_texture_units
!= 0) && (dwStage
>= GL_extensions
.max_texture_units
))) {
1779 unit
= GL_TEXTURE0_WINE
+ dwStage
;
1780 if (unit
!= glThis
->current_active_tex_unit
) {
1781 GL_extensions
.glActiveTexture(unit
);
1782 glThis
->current_active_tex_unit
= unit
;
1785 switch (d3dTexStageStateType
) {
1786 #define GEN_CASE(a) case a: type = #a; break
1787 GEN_CASE(D3DTSS_COLOROP
);
1788 GEN_CASE(D3DTSS_COLORARG1
);
1789 GEN_CASE(D3DTSS_COLORARG2
);
1790 GEN_CASE(D3DTSS_ALPHAOP
);
1791 GEN_CASE(D3DTSS_ALPHAARG1
);
1792 GEN_CASE(D3DTSS_ALPHAARG2
);
1793 GEN_CASE(D3DTSS_BUMPENVMAT00
);
1794 GEN_CASE(D3DTSS_BUMPENVMAT01
);
1795 GEN_CASE(D3DTSS_BUMPENVMAT10
);
1796 GEN_CASE(D3DTSS_BUMPENVMAT11
);
1797 GEN_CASE(D3DTSS_TEXCOORDINDEX
);
1798 GEN_CASE(D3DTSS_ADDRESS
);
1799 GEN_CASE(D3DTSS_ADDRESSU
);
1800 GEN_CASE(D3DTSS_ADDRESSV
);
1801 GEN_CASE(D3DTSS_BORDERCOLOR
);
1802 GEN_CASE(D3DTSS_MAGFILTER
);
1803 GEN_CASE(D3DTSS_MINFILTER
);
1804 GEN_CASE(D3DTSS_MIPFILTER
);
1805 GEN_CASE(D3DTSS_MIPMAPLODBIAS
);
1806 GEN_CASE(D3DTSS_MAXMIPLEVEL
);
1807 GEN_CASE(D3DTSS_MAXANISOTROPY
);
1808 GEN_CASE(D3DTSS_BUMPENVLSCALE
);
1809 GEN_CASE(D3DTSS_BUMPENVLOFFSET
);
1810 GEN_CASE(D3DTSS_TEXTURETRANSFORMFLAGS
);
1812 default: type
= "UNKNOWN";
1815 /* Store the values in the state array */
1816 prev_state
= This
->state_block
.texture_stage_state
[dwStage
][d3dTexStageStateType
- 1];
1817 This
->state_block
.texture_stage_state
[dwStage
][d3dTexStageStateType
- 1] = dwState
;
1818 /* Some special cases when one state modifies more than one... */
1819 if (d3dTexStageStateType
== D3DTSS_ADDRESS
) {
1820 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ADDRESSU
- 1] = dwState
;
1821 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ADDRESSV
- 1] = dwState
;
1826 switch (d3dTexStageStateType
) {
1827 case D3DTSS_MINFILTER
:
1828 case D3DTSS_MIPFILTER
:
1829 if (TRACE_ON(ddraw
)) {
1830 if (d3dTexStageStateType
== D3DTSS_MINFILTER
) {
1831 switch ((D3DTEXTUREMINFILTER
) dwState
) {
1832 case D3DTFN_POINT
: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_POINT\n"); break;
1833 case D3DTFN_LINEAR
: TRACE(" Stage type is : D3DTSS_MINFILTER => D3DTFN_LINEAR\n"); break;
1834 default: FIXME(" Unhandled stage type : D3DTSS_MINFILTER => %08lx\n", dwState
); break;
1837 switch ((D3DTEXTUREMIPFILTER
) dwState
) {
1838 case D3DTFP_NONE
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_NONE\n"); break;
1839 case D3DTFP_POINT
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_POINT\n"); break;
1840 case D3DTFP_LINEAR
: TRACE(" Stage type is : D3DTSS_MIPFILTER => D3DTFP_LINEAR\n"); break;
1841 default: FIXME(" Unhandled stage type : D3DTSS_MIPFILTER => %08lx\n", dwState
); break;
1847 case D3DTSS_MAGFILTER
:
1848 if (TRACE_ON(ddraw
)) {
1849 switch ((D3DTEXTUREMAGFILTER
) dwState
) {
1850 case D3DTFG_POINT
: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_POINT\n"); break;
1851 case D3DTFG_LINEAR
: TRACE(" Stage type is : D3DTSS_MAGFILTER => D3DTFG_LINEAR\n"); break;
1852 default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState
); break;
1857 case D3DTSS_ADDRESS
:
1858 case D3DTSS_ADDRESSU
:
1859 case D3DTSS_ADDRESSV
: {
1860 switch ((D3DTEXTUREADDRESS
) dwState
) {
1861 case D3DTADDRESS_WRAP
: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type
); break;
1862 case D3DTADDRESS_CLAMP
: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type
); break;
1863 case D3DTADDRESS_BORDER
: TRACE(" Stage type is : %s => D3DTADDRESS_BORDER\n", type
); break;
1864 case D3DTADDRESS_MIRROR
:
1865 if (GL_extensions
.mirrored_repeat
== TRUE
) {
1866 TRACE(" Stage type is : %s => D3DTADDRESS_MIRROR\n", type
);
1868 FIXME(" Stage type is : %s => D3DTADDRESS_MIRROR - not supported by GL !\n", type
);
1871 default: FIXME(" Unhandled stage type : %s => %08lx\n", type
, dwState
); break;
1875 case D3DTSS_ALPHAOP
:
1876 case D3DTSS_COLOROP
: {
1878 GLenum parm
= (d3dTexStageStateType
== D3DTSS_ALPHAOP
) ? GL_COMBINE_ALPHA_EXT
: GL_COMBINE_RGB_EXT
;
1883 #define GEN_CASE(a) case a: value = #a; break
1884 GEN_CASE(D3DTOP_DISABLE
);
1885 GEN_CASE(D3DTOP_SELECTARG1
);
1886 GEN_CASE(D3DTOP_SELECTARG2
);
1887 GEN_CASE(D3DTOP_MODULATE
);
1888 GEN_CASE(D3DTOP_MODULATE2X
);
1889 GEN_CASE(D3DTOP_MODULATE4X
);
1890 GEN_CASE(D3DTOP_ADD
);
1891 GEN_CASE(D3DTOP_ADDSIGNED
);
1892 GEN_CASE(D3DTOP_ADDSIGNED2X
);
1893 GEN_CASE(D3DTOP_SUBTRACT
);
1894 GEN_CASE(D3DTOP_ADDSMOOTH
);
1895 GEN_CASE(D3DTOP_BLENDDIFFUSEALPHA
);
1896 GEN_CASE(D3DTOP_BLENDTEXTUREALPHA
);
1897 GEN_CASE(D3DTOP_BLENDFACTORALPHA
);
1898 GEN_CASE(D3DTOP_BLENDTEXTUREALPHAPM
);
1899 GEN_CASE(D3DTOP_BLENDCURRENTALPHA
);
1900 GEN_CASE(D3DTOP_PREMODULATE
);
1901 GEN_CASE(D3DTOP_MODULATEALPHA_ADDCOLOR
);
1902 GEN_CASE(D3DTOP_MODULATECOLOR_ADDALPHA
);
1903 GEN_CASE(D3DTOP_MODULATEINVALPHA_ADDCOLOR
);
1904 GEN_CASE(D3DTOP_MODULATEINVCOLOR_ADDALPHA
);
1905 GEN_CASE(D3DTOP_BUMPENVMAP
);
1906 GEN_CASE(D3DTOP_BUMPENVMAPLUMINANCE
);
1907 GEN_CASE(D3DTOP_DOTPRODUCT3
);
1908 GEN_CASE(D3DTOP_FORCE_DWORD
);
1910 default: value
= "UNKNOWN";
1913 if ((d3dTexStageStateType
== D3DTSS_COLOROP
) && (dwState
== D3DTOP_DISABLE
)) {
1914 glDisable(GL_TEXTURE_2D
);
1915 TRACE(" disabling 2D texturing.\n");
1917 /* Re-enable texturing */
1918 if (This
->current_texture
[0] != NULL
) {
1919 glEnable(GL_TEXTURE_2D
);
1920 TRACE(" enabling 2D texturing.\n");
1923 /* Re-Enable GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT */
1924 if (dwState
!= D3DTOP_DISABLE
) {
1925 if (glThis
->current_tex_env
!= GL_COMBINE_EXT
) {
1926 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE_EXT
);
1927 glThis
->current_tex_env
= GL_COMBINE_EXT
;
1931 /* Now set up the operand correctly */
1933 case D3DTOP_DISABLE
:
1934 /* Contrary to the docs, alpha can be disabled when colorop is enabled
1935 and it works, so ignore this op */
1936 TRACE(" Note : disable ALPHAOP but COLOROP enabled!\n");
1939 case D3DTOP_SELECTARG1
:
1940 case D3DTOP_SELECTARG2
:
1941 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_REPLACE
);
1944 case D3DTOP_MODULATE4X
:
1945 scale
= scale
* 2; /* Drop through */
1946 case D3DTOP_MODULATE2X
:
1947 scale
= scale
* 2; /* Drop through */
1948 case D3DTOP_MODULATE
:
1949 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_MODULATE
);
1953 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_ADD
);
1956 case D3DTOP_ADDSIGNED2X
:
1957 scale
= scale
* 2; /* Drop through */
1958 case D3DTOP_ADDSIGNED
:
1959 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_ADD_SIGNED_EXT
);
1962 /* For the four blending modes, use the Arg2 parameter */
1963 case D3DTOP_BLENDDIFFUSEALPHA
:
1964 case D3DTOP_BLENDTEXTUREALPHA
:
1965 case D3DTOP_BLENDFACTORALPHA
:
1966 case D3DTOP_BLENDCURRENTALPHA
: {
1967 GLenum src
= GL_PRIMARY_COLOR_EXT
; /* Just to prevent a compiler warning.. */
1970 case D3DTOP_BLENDDIFFUSEALPHA
: src
= GL_PRIMARY_COLOR_EXT
;
1971 case D3DTOP_BLENDTEXTUREALPHA
: src
= GL_TEXTURE
;
1972 case D3DTOP_BLENDFACTORALPHA
: src
= GL_CONSTANT_EXT
;
1973 case D3DTOP_BLENDCURRENTALPHA
: src
= GL_PREVIOUS_EXT
;
1976 glTexEnvi(GL_TEXTURE_ENV
, parm
, GL_INTERPOLATE_EXT
);
1977 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB_EXT
, src
);
1978 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB_EXT
, GL_SRC_ALPHA
);
1979 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA_EXT
, src
);
1980 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA_EXT
, GL_SRC_ALPHA
);
1989 if (((prev_state
== D3DTOP_SELECTARG2
) && (dwState
!= D3DTOP_SELECTARG2
)) ||
1990 ((dwState
== D3DTOP_SELECTARG2
) && (prev_state
!= D3DTOP_SELECTARG2
))) {
1991 /* Switch the arguments if needed... */
1992 if (d3dTexStageStateType
== D3DTSS_COLOROP
) {
1993 handle_color_alpha_args(This
, dwStage
, D3DTSS_COLORARG1
,
1994 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLORARG1
- 1],
1996 handle_color_alpha_args(This
, dwStage
, D3DTSS_COLORARG2
,
1997 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLORARG2
- 1],
2000 handle_color_alpha_args(This
, dwStage
, D3DTSS_ALPHAARG1
,
2001 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAARG1
- 1],
2003 handle_color_alpha_args(This
, dwStage
, D3DTSS_ALPHAARG2
,
2004 This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAARG2
- 1],
2010 if (d3dTexStageStateType
== D3DTSS_ALPHAOP
) {
2011 glTexEnvi(GL_TEXTURE_ENV
, GL_ALPHA_SCALE
, scale
);
2013 glTexEnvi(GL_TEXTURE_ENV
, GL_RGB_SCALE_EXT
, scale
);
2015 TRACE(" Stage type is : %s => %s\n", type
, value
);
2017 FIXME(" Unhandled stage type is : %s => %s\n", type
, value
);
2021 case D3DTSS_COLORARG1
:
2022 case D3DTSS_COLORARG2
:
2023 case D3DTSS_ALPHAARG1
:
2024 case D3DTSS_ALPHAARG2
: {
2025 const char *value
, *value_comp
= "", *value_alpha
= "";
2027 D3DTEXTUREOP tex_op
;
2029 switch (dwState
& D3DTA_SELECTMASK
) {
2030 #define GEN_CASE(a) case a: value = #a; break
2031 GEN_CASE(D3DTA_DIFFUSE
);
2032 GEN_CASE(D3DTA_CURRENT
);
2033 GEN_CASE(D3DTA_TEXTURE
);
2034 GEN_CASE(D3DTA_TFACTOR
);
2035 GEN_CASE(D3DTA_SPECULAR
);
2037 default: value
= "UNKNOWN";
2039 if (dwState
& D3DTA_COMPLEMENT
) {
2040 value_comp
= " | D3DTA_COMPLEMENT";
2042 if (dwState
& D3DTA_ALPHAREPLICATE
) {
2043 value_alpha
= " | D3DTA_ALPHAREPLICATE";
2046 if ((d3dTexStageStateType
== D3DTSS_COLORARG1
) || (d3dTexStageStateType
== D3DTSS_COLORARG2
)) {
2047 tex_op
= This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_COLOROP
- 1];
2049 tex_op
= This
->state_block
.texture_stage_state
[dwStage
][D3DTSS_ALPHAOP
- 1];
2052 handled
= handle_color_alpha_args(This
, dwStage
, d3dTexStageStateType
, dwState
, tex_op
);
2055 TRACE(" Stage type : %s => %s%s%s\n", type
, value
, value_comp
, value_alpha
);
2057 FIXME(" Unhandled stage type : %s => %s%s%s\n", type
, value
, value_comp
, value_alpha
);
2061 case D3DTSS_MIPMAPLODBIAS
: {
2062 D3DVALUE value
= *((D3DVALUE
*) &dwState
);
2063 BOOLEAN handled
= TRUE
;
2065 if ((value
!= 0.0) && (GL_extensions
.mipmap_lodbias
== FALSE
))
2069 TRACE(" Stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value
);
2070 glTexEnvf(GL_TEXTURE_FILTER_CONTROL_WINE
, GL_TEXTURE_LOD_BIAS_WINE
, value
);
2072 FIXME(" Unhandled stage type : D3DTSS_MIPMAPLODBIAS => %f\n", value
);
2076 case D3DTSS_MAXMIPLEVEL
:
2077 TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState
);
2080 case D3DTSS_BORDERCOLOR
:
2081 TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
2082 ((dwState
>> 16) & 0xFF),
2083 ((dwState
>> 8) & 0xFF),
2084 ((dwState
>> 0) & 0xFF),
2085 ((dwState
>> 24) & 0xFF));
2088 case D3DTSS_TEXCOORDINDEX
: {
2089 BOOLEAN handled
= TRUE
;
2092 switch (dwState
& 0xFFFF0000) {
2093 #define GEN_CASE(a) case a: value = #a; break
2094 GEN_CASE(D3DTSS_TCI_PASSTHRU
);
2095 GEN_CASE(D3DTSS_TCI_CAMERASPACENORMAL
);
2096 GEN_CASE(D3DTSS_TCI_CAMERASPACEPOSITION
);
2097 GEN_CASE(D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR
);
2099 default: value
= "UNKNOWN";
2101 if ((dwState
& 0xFFFF0000) != D3DTSS_TCI_PASSTHRU
)
2105 TRACE(" Stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState
& 0x0000FFFF, value
);
2107 FIXME(" Unhandled stage type : D3DTSS_TEXCOORDINDEX => %ld | %s\n", dwState
& 0x0000FFFF, value
);
2111 case D3DTSS_TEXTURETRANSFORMFLAGS
: {
2112 const char *projected
= "", *value
;
2113 BOOLEAN handled
= TRUE
;
2114 switch (dwState
& 0xFF) {
2115 #define GEN_CASE(a) case a: value = #a; break
2116 GEN_CASE(D3DTTFF_DISABLE
);
2117 GEN_CASE(D3DTTFF_COUNT1
);
2118 GEN_CASE(D3DTTFF_COUNT2
);
2119 GEN_CASE(D3DTTFF_COUNT3
);
2120 GEN_CASE(D3DTTFF_COUNT4
);
2122 default: value
= "UNKNOWN";
2124 if (dwState
& D3DTTFF_PROJECTED
) {
2125 projected
= " | D3DTTFF_PROJECTED";
2129 if ((dwState
& 0xFF) != D3DTTFF_DISABLE
) {
2130 This
->matrices_updated(This
, TEXMAT0_CHANGED
<< dwStage
);
2133 if (handled
== TRUE
) {
2134 TRACE(" Stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value
, projected
);
2136 FIXME(" Unhandled stage type : D3DTSS_TEXTURETRANSFORMFLAGS => %s%s\n", value
, projected
);
2141 FIXME(" Unhandled stage type : %s => %08lx\n", type
, dwState
);
2151 draw_primitive_handle_textures(IDirect3DDeviceImpl
*This
)
2153 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2156 for (stage
= 0; stage
< MAX_TEXTURES
; stage
++) {
2157 IDirectDrawSurfaceImpl
*surf_ptr
= This
->current_texture
[stage
];
2160 /* First check if we need to bind any other texture for this stage */
2161 if (This
->current_texture
[stage
] != glThis
->current_bound_texture
[stage
]) {
2162 if (This
->current_texture
[stage
] == NULL
) {
2163 TRACE(" disabling 2D texturing for stage %ld.\n", stage
);
2165 unit
= GL_TEXTURE0_WINE
+ stage
;
2166 if (unit
!= glThis
->current_active_tex_unit
) {
2167 GL_extensions
.glActiveTexture(unit
);
2168 glThis
->current_active_tex_unit
= unit
;
2170 glBindTexture(GL_TEXTURE_2D
, 0);
2173 glDisable(GL_TEXTURE_2D
);
2176 GLenum tex_name
= ((IDirect3DTextureGLImpl
*) surf_ptr
->tex_private
)->tex_name
;
2178 unit
= GL_TEXTURE0_WINE
+ stage
;
2179 if (unit
!= glThis
->current_active_tex_unit
) {
2180 GL_extensions
.glActiveTexture(unit
);
2181 glThis
->current_active_tex_unit
= unit
;
2184 if (glThis
->current_bound_texture
[stage
] == NULL
) {
2185 if (This
->state_block
.texture_stage_state
[stage
][D3DTSS_COLOROP
- 1] != D3DTOP_DISABLE
) {
2186 TRACE(" enabling 2D texturing and");
2187 glEnable(GL_TEXTURE_2D
);
2190 TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name
, stage
);
2191 glBindTexture(GL_TEXTURE_2D
, tex_name
);
2194 glThis
->current_bound_texture
[stage
] = This
->current_texture
[stage
];
2196 if (glThis
->current_bound_texture
[stage
] == NULL
) {
2197 TRACE(" displaying without texturing activated for stage %ld.\n", stage
);
2199 TRACE(" using already bound texture id %d for stage %ld.\n",
2200 ((IDirect3DTextureGLImpl
*) (glThis
->current_bound_texture
[stage
])->tex_private
)->tex_name
, stage
);
2204 /* If no texure valid for this stage, go out of the loop */
2205 if (This
->current_texture
[stage
] == NULL
) break;
2207 /* Then check if we need to flush this texture to GL or not (ie did it change) ?.
2208 This will also update the various texture parameters if needed.
2210 gltex_upload_texture(surf_ptr
, This
, stage
);
2217 GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface
,
2219 LPDIRECTDRAWSURFACE7 lpTexture2
)
2221 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2223 TRACE("(%p/%p)->(%08lx,%p)\n", This
, iface
, dwStage
, lpTexture2
);
2225 if (((GL_extensions
.max_texture_units
== 0) && (dwStage
> 0)) ||
2226 ((GL_extensions
.max_texture_units
!= 0) && (dwStage
>= GL_extensions
.max_texture_units
))) {
2227 if (lpTexture2
!= NULL
) {
2228 WARN(" setting a texture to a non-supported texture stage !\n");
2233 if (This
->current_texture
[dwStage
] != NULL
) {
2234 IDirectDrawSurface7_Release(ICOM_INTERFACE(This
->current_texture
[dwStage
], IDirectDrawSurface7
));
2237 if (lpTexture2
== NULL
) {
2238 This
->current_texture
[dwStage
] = NULL
;
2240 IDirectDrawSurfaceImpl
*tex_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, lpTexture2
);
2241 IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl
, IDirectDrawSurface7
));
2242 This
->current_texture
[dwStage
] = tex_impl
;
2249 GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface
,
2250 LPD3DDEVICEDESC7 lpD3DHELDevDesc
)
2252 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2253 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpD3DHELDevDesc
);
2255 fill_opengl_caps_7(lpD3DHELDevDesc
);
2257 TRACE(" returning caps : no dump function yet.\n");
2263 GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface
,
2264 LPD3DMATERIAL7 lpMat
)
2266 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2267 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpMat
);
2269 if (TRACE_ON(ddraw
)) {
2270 TRACE(" material is : \n");
2271 dump_D3DMATERIAL7(lpMat
);
2274 This
->current_material
= *lpMat
;
2277 glMaterialfv(GL_FRONT_AND_BACK
,
2279 (float *) &(This
->current_material
.u
.diffuse
));
2280 glMaterialfv(GL_FRONT_AND_BACK
,
2282 (float *) &(This
->current_material
.u1
.ambient
));
2283 glMaterialfv(GL_FRONT_AND_BACK
,
2285 (float *) &(This
->current_material
.u2
.specular
));
2286 glMaterialfv(GL_FRONT_AND_BACK
,
2288 (float *) &(This
->current_material
.u3
.emissive
));
2289 glMaterialf(GL_FRONT_AND_BACK
,
2291 This
->current_material
.u4
.power
); /* Not sure about this... */
2299 GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface
,
2301 LPD3DLIGHT7 lpLight
)
2303 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2304 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2305 TRACE("(%p/%p)->(%08lx,%p)\n", This
, iface
, dwLightIndex
, lpLight
);
2307 if (TRACE_ON(ddraw
)) {
2308 TRACE(" setting light : \n");
2309 dump_D3DLIGHT7(lpLight
);
2312 if (dwLightIndex
>= MAX_LIGHTS
) return DDERR_INVALIDPARAMS
;
2313 This
->set_lights
|= 0x00000001 << dwLightIndex
;
2314 This
->light_parameters
[dwLightIndex
] = *lpLight
;
2316 /* Some checks to print out nice warnings :-) */
2317 switch (lpLight
->dltType
) {
2318 case D3DLIGHT_DIRECTIONAL
:
2319 case D3DLIGHT_POINT
:
2320 /* These are handled properly... */
2324 if ((lpLight
->dvTheta
!= 0.0) ||
2325 (lpLight
->dvTheta
!= lpLight
->dvPhi
)) {
2326 ERR("dvTheta not fully supported yet !\n");
2331 ERR("Light type not handled yet : %08x !\n", lpLight
->dltType
);
2334 /* This will force the Light setting on next drawing of primitives */
2335 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2341 GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface
,
2345 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2346 TRACE("(%p/%p)->(%08lx,%d)\n", This
, iface
, dwLightIndex
, bEnable
);
2348 if (dwLightIndex
>= MAX_LIGHTS
) return DDERR_INVALIDPARAMS
;
2352 if (((0x00000001 << dwLightIndex
) & This
->set_lights
) == 0) {
2353 /* Set the default parameters.. */
2354 TRACE(" setting default light parameters...\n");
2355 GL_IDirect3DDeviceImpl_7_SetLight(iface
, dwLightIndex
, &(This
->light_parameters
[dwLightIndex
]));
2357 glEnable(GL_LIGHT0
+ dwLightIndex
);
2358 if ((This
->active_lights
& (0x00000001 << dwLightIndex
)) == 0) {
2359 /* This light gets active... Need to update its parameters to GL before the next drawing */
2360 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2362 This
->active_lights
|= 0x00000001 << dwLightIndex
;
2363 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2366 glDisable(GL_LIGHT0
+ dwLightIndex
);
2367 This
->active_lights
&= ~(0x00000001 << dwLightIndex
);
2375 GL_IDirect3DDeviceImpl_7_SetClipPlane(LPDIRECT3DDEVICE7 iface
, DWORD dwIndex
, CONST D3DVALUE
* pPlaneEquation
)
2377 ICOM_THIS(IDirect3DDeviceImpl
,iface
);
2378 IDirect3DDeviceGLImpl
* glThis
= (IDirect3DDeviceGLImpl
*) This
;
2380 TRACE("(%p)->(%ld,%p)\n", This
, dwIndex
, pPlaneEquation
);
2382 if (dwIndex
>= This
->max_clipping_planes
) {
2383 return DDERR_INVALIDPARAMS
;
2386 TRACE(" clip plane %ld : %f %f %f %f\n", dwIndex
, pPlaneEquation
[0], pPlaneEquation
[1], pPlaneEquation
[2], pPlaneEquation
[3] );
2388 memcpy(This
->clipping_planes
[dwIndex
].plane
, pPlaneEquation
, sizeof(D3DVALUE
[4]));
2390 /* This is to force the reset of the transformation matrices on the next drawing.
2391 * This is needed to use the correct matrices for the various clipping planes.
2393 glThis
->transform_state
= GL_TRANSFORM_NONE
;
2399 GL_IDirect3DDeviceImpl_7_SetViewport(LPDIRECT3DDEVICE7 iface
,
2400 LPD3DVIEWPORT7 lpData
)
2402 ICOM_THIS_FROM(IDirect3DDeviceImpl
, IDirect3DDevice7
, iface
);
2403 TRACE("(%p/%p)->(%p)\n", This
, iface
, lpData
);
2405 if (TRACE_ON(ddraw
)) {
2406 TRACE(" viewport is : \n");
2407 TRACE(" - dwX = %ld dwY = %ld\n",
2408 lpData
->dwX
, lpData
->dwY
);
2409 TRACE(" - dwWidth = %ld dwHeight = %ld\n",
2410 lpData
->dwWidth
, lpData
->dwHeight
);
2411 TRACE(" - dvMinZ = %f dvMaxZ = %f\n",
2412 lpData
->dvMinZ
, lpData
->dvMaxZ
);
2416 /* Set the viewport */
2417 if ((lpData
->dvMinZ
!= This
->active_viewport
.dvMinZ
) ||
2418 (lpData
->dvMaxZ
!= This
->active_viewport
.dvMaxZ
)) {
2419 glDepthRange(lpData
->dvMinZ
, lpData
->dvMaxZ
);
2421 if ((lpData
->dwX
!= This
->active_viewport
.dwX
) ||
2422 (lpData
->dwY
!= This
->active_viewport
.dwY
) ||
2423 (lpData
->dwWidth
!= This
->active_viewport
.dwWidth
) ||
2424 (lpData
->dwHeight
!= This
->active_viewport
.dwHeight
)) {
2425 glViewport(lpData
->dwX
,
2426 This
->surface
->surface_desc
.dwHeight
- (lpData
->dwHeight
+ lpData
->dwY
),
2427 lpData
->dwWidth
, lpData
->dwHeight
);
2432 This
->active_viewport
= *lpData
;
2437 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2438 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
2440 # define XCAST(fun) (void*)
2443 ICOM_VTABLE(IDirect3DDevice7
) VTABLE_IDirect3DDevice7
=
2445 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2446 XCAST(QueryInterface
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_QueryInterface
,
2447 XCAST(AddRef
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_AddRef
,
2448 XCAST(Release
) GL_IDirect3DDeviceImpl_7_3T_2T_1T_Release
,
2449 XCAST(GetCaps
) GL_IDirect3DDeviceImpl_7_GetCaps
,
2450 XCAST(EnumTextureFormats
) GL_IDirect3DDeviceImpl_7_3T_EnumTextureFormats
,
2451 XCAST(BeginScene
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene
,
2452 XCAST(EndScene
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_EndScene
,
2453 XCAST(GetDirect3D
) Main_IDirect3DDeviceImpl_7_3T_2T_1T_GetDirect3D
,
2454 XCAST(SetRenderTarget
) Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget
,
2455 XCAST(GetRenderTarget
) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderTarget
,
2456 XCAST(Clear
) Main_IDirect3DDeviceImpl_7_Clear
,
2457 XCAST(SetTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_SetTransform
,
2458 XCAST(GetTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_GetTransform
,
2459 XCAST(SetViewport
) GL_IDirect3DDeviceImpl_7_SetViewport
,
2460 XCAST(MultiplyTransform
) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform
,
2461 XCAST(GetViewport
) Main_IDirect3DDeviceImpl_7_GetViewport
,
2462 XCAST(SetMaterial
) GL_IDirect3DDeviceImpl_7_SetMaterial
,
2463 XCAST(GetMaterial
) Main_IDirect3DDeviceImpl_7_GetMaterial
,
2464 XCAST(SetLight
) GL_IDirect3DDeviceImpl_7_SetLight
,
2465 XCAST(GetLight
) Main_IDirect3DDeviceImpl_7_GetLight
,
2466 XCAST(SetRenderState
) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState
,
2467 XCAST(GetRenderState
) GL_IDirect3DDeviceImpl_7_3T_2T_GetRenderState
,
2468 XCAST(BeginStateBlock
) Main_IDirect3DDeviceImpl_7_BeginStateBlock
,
2469 XCAST(EndStateBlock
) Main_IDirect3DDeviceImpl_7_EndStateBlock
,
2470 XCAST(PreLoad
) Main_IDirect3DDeviceImpl_7_PreLoad
,
2471 XCAST(DrawPrimitive
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitive
,
2472 XCAST(DrawIndexedPrimitive
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitive
,
2473 XCAST(SetClipStatus
) Main_IDirect3DDeviceImpl_7_3T_2T_SetClipStatus
,
2474 XCAST(GetClipStatus
) Main_IDirect3DDeviceImpl_7_3T_2T_GetClipStatus
,
2475 XCAST(DrawPrimitiveStrided
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveStrided
,
2476 XCAST(DrawIndexedPrimitiveStrided
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveStrided
,
2477 XCAST(DrawPrimitiveVB
) GL_IDirect3DDeviceImpl_7_3T_DrawPrimitiveVB
,
2478 XCAST(DrawIndexedPrimitiveVB
) GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB
,
2479 XCAST(ComputeSphereVisibility
) Main_IDirect3DDeviceImpl_7_3T_ComputeSphereVisibility
,
2480 XCAST(GetTexture
) Main_IDirect3DDeviceImpl_7_3T_GetTexture
,
2481 XCAST(SetTexture
) GL_IDirect3DDeviceImpl_7_3T_SetTexture
,
2482 XCAST(GetTextureStageState
) Main_IDirect3DDeviceImpl_7_3T_GetTextureStageState
,
2483 XCAST(SetTextureStageState
) GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState
,
2484 XCAST(ValidateDevice
) Main_IDirect3DDeviceImpl_7_3T_ValidateDevice
,
2485 XCAST(ApplyStateBlock
) Main_IDirect3DDeviceImpl_7_ApplyStateBlock
,
2486 XCAST(CaptureStateBlock
) Main_IDirect3DDeviceImpl_7_CaptureStateBlock
,
2487 XCAST(DeleteStateBlock
) Main_IDirect3DDeviceImpl_7_DeleteStateBlock
,
2488 XCAST(CreateStateBlock
) Main_IDirect3DDeviceImpl_7_CreateStateBlock
,
2489 XCAST(Load
) Main_IDirect3DDeviceImpl_7_Load
,
2490 XCAST(LightEnable
) GL_IDirect3DDeviceImpl_7_LightEnable
,
2491 XCAST(GetLightEnable
) Main_IDirect3DDeviceImpl_7_GetLightEnable
,
2492 XCAST(SetClipPlane
) GL_IDirect3DDeviceImpl_7_SetClipPlane
,
2493 XCAST(GetClipPlane
) Main_IDirect3DDeviceImpl_7_GetClipPlane
,
2494 XCAST(GetInfo
) Main_IDirect3DDeviceImpl_7_GetInfo
,
2497 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2502 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2503 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice3.fun))
2505 # define XCAST(fun) (void*)
2508 ICOM_VTABLE(IDirect3DDevice3
) VTABLE_IDirect3DDevice3
=
2510 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2511 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_3_QueryInterface
,
2512 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_3_AddRef
,
2513 XCAST(Release
) Thunk_IDirect3DDeviceImpl_3_Release
,
2514 XCAST(GetCaps
) GL_IDirect3DDeviceImpl_3_2T_1T_GetCaps
,
2515 XCAST(GetStats
) Main_IDirect3DDeviceImpl_3_2T_1T_GetStats
,
2516 XCAST(AddViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_AddViewport
,
2517 XCAST(DeleteViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_DeleteViewport
,
2518 XCAST(NextViewport
) Main_IDirect3DDeviceImpl_3_2T_1T_NextViewport
,
2519 XCAST(EnumTextureFormats
) Thunk_IDirect3DDeviceImpl_3_EnumTextureFormats
,
2520 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_3_BeginScene
,
2521 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_3_EndScene
,
2522 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_3_GetDirect3D
,
2523 XCAST(SetCurrentViewport
) Main_IDirect3DDeviceImpl_3_2T_SetCurrentViewport
,
2524 XCAST(GetCurrentViewport
) Main_IDirect3DDeviceImpl_3_2T_GetCurrentViewport
,
2525 XCAST(SetRenderTarget
) Thunk_IDirect3DDeviceImpl_3_SetRenderTarget
,
2526 XCAST(GetRenderTarget
) Thunk_IDirect3DDeviceImpl_3_GetRenderTarget
,
2527 XCAST(Begin
) Main_IDirect3DDeviceImpl_3_Begin
,
2528 XCAST(BeginIndexed
) Main_IDirect3DDeviceImpl_3_BeginIndexed
,
2529 XCAST(Vertex
) Main_IDirect3DDeviceImpl_3_2T_Vertex
,
2530 XCAST(Index
) Main_IDirect3DDeviceImpl_3_2T_Index
,
2531 XCAST(End
) Main_IDirect3DDeviceImpl_3_2T_End
,
2532 XCAST(GetRenderState
) Thunk_IDirect3DDeviceImpl_3_GetRenderState
,
2533 XCAST(SetRenderState
) Thunk_IDirect3DDeviceImpl_3_SetRenderState
,
2534 XCAST(GetLightState
) Main_IDirect3DDeviceImpl_3_2T_GetLightState
,
2535 XCAST(SetLightState
) GL_IDirect3DDeviceImpl_3_2T_SetLightState
,
2536 XCAST(SetTransform
) Thunk_IDirect3DDeviceImpl_3_SetTransform
,
2537 XCAST(GetTransform
) Thunk_IDirect3DDeviceImpl_3_GetTransform
,
2538 XCAST(MultiplyTransform
) Thunk_IDirect3DDeviceImpl_3_MultiplyTransform
,
2539 XCAST(DrawPrimitive
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitive
,
2540 XCAST(DrawIndexedPrimitive
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitive
,
2541 XCAST(SetClipStatus
) Thunk_IDirect3DDeviceImpl_3_SetClipStatus
,
2542 XCAST(GetClipStatus
) Thunk_IDirect3DDeviceImpl_3_GetClipStatus
,
2543 XCAST(DrawPrimitiveStrided
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveStrided
,
2544 XCAST(DrawIndexedPrimitiveStrided
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveStrided
,
2545 XCAST(DrawPrimitiveVB
) Thunk_IDirect3DDeviceImpl_3_DrawPrimitiveVB
,
2546 XCAST(DrawIndexedPrimitiveVB
) Thunk_IDirect3DDeviceImpl_3_DrawIndexedPrimitiveVB
,
2547 XCAST(ComputeSphereVisibility
) Thunk_IDirect3DDeviceImpl_3_ComputeSphereVisibility
,
2548 XCAST(GetTexture
) Thunk_IDirect3DDeviceImpl_3_GetTexture
,
2549 XCAST(SetTexture
) Thunk_IDirect3DDeviceImpl_3_SetTexture
,
2550 XCAST(GetTextureStageState
) Thunk_IDirect3DDeviceImpl_3_GetTextureStageState
,
2551 XCAST(SetTextureStageState
) Thunk_IDirect3DDeviceImpl_3_SetTextureStageState
,
2552 XCAST(ValidateDevice
) Thunk_IDirect3DDeviceImpl_3_ValidateDevice
,
2555 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2560 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2561 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice2.fun))
2563 # define XCAST(fun) (void*)
2566 ICOM_VTABLE(IDirect3DDevice2
) VTABLE_IDirect3DDevice2
=
2568 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2569 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_2_QueryInterface
,
2570 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_2_AddRef
,
2571 XCAST(Release
) Thunk_IDirect3DDeviceImpl_2_Release
,
2572 XCAST(GetCaps
) Thunk_IDirect3DDeviceImpl_2_GetCaps
,
2573 XCAST(SwapTextureHandles
) Main_IDirect3DDeviceImpl_2_1T_SwapTextureHandles
,
2574 XCAST(GetStats
) Thunk_IDirect3DDeviceImpl_2_GetStats
,
2575 XCAST(AddViewport
) Thunk_IDirect3DDeviceImpl_2_AddViewport
,
2576 XCAST(DeleteViewport
) Thunk_IDirect3DDeviceImpl_2_DeleteViewport
,
2577 XCAST(NextViewport
) Thunk_IDirect3DDeviceImpl_2_NextViewport
,
2578 XCAST(EnumTextureFormats
) GL_IDirect3DDeviceImpl_2_1T_EnumTextureFormats
,
2579 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_2_BeginScene
,
2580 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_2_EndScene
,
2581 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_2_GetDirect3D
,
2582 XCAST(SetCurrentViewport
) Thunk_IDirect3DDeviceImpl_2_SetCurrentViewport
,
2583 XCAST(GetCurrentViewport
) Thunk_IDirect3DDeviceImpl_2_GetCurrentViewport
,
2584 XCAST(SetRenderTarget
) Thunk_IDirect3DDeviceImpl_2_SetRenderTarget
,
2585 XCAST(GetRenderTarget
) Thunk_IDirect3DDeviceImpl_2_GetRenderTarget
,
2586 XCAST(Begin
) Main_IDirect3DDeviceImpl_2_Begin
,
2587 XCAST(BeginIndexed
) Main_IDirect3DDeviceImpl_2_BeginIndexed
,
2588 XCAST(Vertex
) Thunk_IDirect3DDeviceImpl_2_Vertex
,
2589 XCAST(Index
) Thunk_IDirect3DDeviceImpl_2_Index
,
2590 XCAST(End
) Thunk_IDirect3DDeviceImpl_2_End
,
2591 XCAST(GetRenderState
) Thunk_IDirect3DDeviceImpl_2_GetRenderState
,
2592 XCAST(SetRenderState
) Thunk_IDirect3DDeviceImpl_2_SetRenderState
,
2593 XCAST(GetLightState
) Thunk_IDirect3DDeviceImpl_2_GetLightState
,
2594 XCAST(SetLightState
) Thunk_IDirect3DDeviceImpl_2_SetLightState
,
2595 XCAST(SetTransform
) Thunk_IDirect3DDeviceImpl_2_SetTransform
,
2596 XCAST(GetTransform
) Thunk_IDirect3DDeviceImpl_2_GetTransform
,
2597 XCAST(MultiplyTransform
) Thunk_IDirect3DDeviceImpl_2_MultiplyTransform
,
2598 XCAST(DrawPrimitive
) GL_IDirect3DDeviceImpl_2_DrawPrimitive
,
2599 XCAST(DrawIndexedPrimitive
) GL_IDirect3DDeviceImpl_2_DrawIndexedPrimitive
,
2600 XCAST(SetClipStatus
) Thunk_IDirect3DDeviceImpl_2_SetClipStatus
,
2601 XCAST(GetClipStatus
) Thunk_IDirect3DDeviceImpl_2_GetClipStatus
,
2604 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2609 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2610 # define XCAST(fun) (typeof(VTABLE_IDirect3DDevice.fun))
2612 # define XCAST(fun) (void*)
2615 ICOM_VTABLE(IDirect3DDevice
) VTABLE_IDirect3DDevice
=
2617 ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE
2618 XCAST(QueryInterface
) Thunk_IDirect3DDeviceImpl_1_QueryInterface
,
2619 XCAST(AddRef
) Thunk_IDirect3DDeviceImpl_1_AddRef
,
2620 XCAST(Release
) Thunk_IDirect3DDeviceImpl_1_Release
,
2621 XCAST(Initialize
) Main_IDirect3DDeviceImpl_1_Initialize
,
2622 XCAST(GetCaps
) Thunk_IDirect3DDeviceImpl_1_GetCaps
,
2623 XCAST(SwapTextureHandles
) Thunk_IDirect3DDeviceImpl_1_SwapTextureHandles
,
2624 XCAST(CreateExecuteBuffer
) GL_IDirect3DDeviceImpl_1_CreateExecuteBuffer
,
2625 XCAST(GetStats
) Thunk_IDirect3DDeviceImpl_1_GetStats
,
2626 XCAST(Execute
) Main_IDirect3DDeviceImpl_1_Execute
,
2627 XCAST(AddViewport
) Thunk_IDirect3DDeviceImpl_1_AddViewport
,
2628 XCAST(DeleteViewport
) Thunk_IDirect3DDeviceImpl_1_DeleteViewport
,
2629 XCAST(NextViewport
) Thunk_IDirect3DDeviceImpl_1_NextViewport
,
2630 XCAST(Pick
) Main_IDirect3DDeviceImpl_1_Pick
,
2631 XCAST(GetPickRecords
) Main_IDirect3DDeviceImpl_1_GetPickRecords
,
2632 XCAST(EnumTextureFormats
) Thunk_IDirect3DDeviceImpl_1_EnumTextureFormats
,
2633 XCAST(CreateMatrix
) Main_IDirect3DDeviceImpl_1_CreateMatrix
,
2634 XCAST(SetMatrix
) Main_IDirect3DDeviceImpl_1_SetMatrix
,
2635 XCAST(GetMatrix
) Main_IDirect3DDeviceImpl_1_GetMatrix
,
2636 XCAST(DeleteMatrix
) Main_IDirect3DDeviceImpl_1_DeleteMatrix
,
2637 XCAST(BeginScene
) Thunk_IDirect3DDeviceImpl_1_BeginScene
,
2638 XCAST(EndScene
) Thunk_IDirect3DDeviceImpl_1_EndScene
,
2639 XCAST(GetDirect3D
) Thunk_IDirect3DDeviceImpl_1_GetDirect3D
,
2642 #if !defined(__STRICT_ANSI__) && defined(__GNUC__)
2646 static HRESULT
d3ddevice_clear(IDirect3DDeviceImpl
*This
,
2647 WINE_GL_BUFFER_TYPE buffer_type
,
2655 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
2656 GLbitfield bitfield
= 0;
2660 TRACE("(%p)->(%08lx,%p,%08lx,%08lx,%f,%08lx)\n", This
, dwCount
, lpRects
, dwFlags
, dwColor
, dvZ
, dwStencil
);
2661 if (TRACE_ON(ddraw
)) {
2664 TRACE(" rectangles : \n");
2665 for (i
= 0; i
< dwCount
; i
++) {
2666 TRACE(" - %ld x %ld %ld x %ld\n", lpRects
[i
].u1
.x1
, lpRects
[i
].u2
.y1
, lpRects
[i
].u3
.x2
, lpRects
[i
].u4
.y2
);
2675 rect
.u3
.x2
= This
->surface
->surface_desc
.dwWidth
;
2676 rect
.u4
.y2
= This
->surface
->surface_desc
.dwHeight
;
2680 /* Clears the screen */
2683 if (dwFlags
& D3DCLEAR_TARGET
) {
2684 if (glThis
->state
[buffer_type
] == SURFACE_MEMORY_DIRTY
) {
2685 /* TODO: optimize here the case where Clear changes all the screen... */
2686 This
->flush_to_framebuffer(This
, &(glThis
->lock_rect
[buffer_type
]), glThis
->lock_surf
[buffer_type
]);
2688 glThis
->state
[buffer_type
] = SURFACE_GL
;
2691 if (dwFlags
& D3DCLEAR_ZBUFFER
) {
2692 bitfield
|= GL_DEPTH_BUFFER_BIT
;
2693 if (glThis
->depth_mask
== FALSE
) {
2694 glDepthMask(GL_TRUE
); /* Enables Z writing to be sure to delete also the Z buffer */
2696 if (dvZ
!= glThis
->prev_clear_Z
) {
2698 glThis
->prev_clear_Z
= dvZ
;
2700 TRACE(" depth value : %f\n", dvZ
);
2702 if (dwFlags
& D3DCLEAR_STENCIL
) {
2703 bitfield
|= GL_STENCIL_BUFFER_BIT
;
2704 if (dwStencil
!= glThis
->prev_clear_stencil
) {
2705 glClearStencil(dwStencil
);
2706 glThis
->prev_clear_stencil
= dwStencil
;
2708 TRACE(" stencil value : %ld\n", dwStencil
);
2710 if (dwFlags
& D3DCLEAR_TARGET
) {
2711 bitfield
|= GL_COLOR_BUFFER_BIT
;
2712 if (dwColor
!= glThis
->prev_clear_color
) {
2713 glClearColor(((dwColor
>> 16) & 0xFF) / 255.0,
2714 ((dwColor
>> 8) & 0xFF) / 255.0,
2715 ((dwColor
>> 0) & 0xFF) / 255.0,
2716 ((dwColor
>> 24) & 0xFF) / 255.0);
2717 glThis
->prev_clear_color
= dwColor
;
2719 TRACE(" color value (ARGB) : %08lx\n", dwColor
);
2722 glEnable(GL_SCISSOR_TEST
);
2723 for (i
= 0; i
< dwCount
; i
++) {
2724 glScissor(lpRects
[i
].u1
.x1
, This
->surface
->surface_desc
.dwHeight
- lpRects
[i
].u4
.y2
,
2725 lpRects
[i
].u3
.x2
- lpRects
[i
].u1
.x1
, lpRects
[i
].u4
.y2
- lpRects
[i
].u2
.y1
);
2728 glDisable(GL_SCISSOR_TEST
);
2730 if (dwFlags
& D3DCLEAR_ZBUFFER
) {
2731 if (glThis
->depth_mask
== FALSE
) glDepthMask(GL_FALSE
);
2739 static HRESULT
d3ddevice_clear_back(IDirect3DDeviceImpl
*This
,
2747 return d3ddevice_clear(This
, WINE_GL_BUFFER_BACK
, dwCount
, lpRects
, dwFlags
, dwColor
, dvZ
, dwStencil
);
2751 setup_rect_and_surface_for_blt(IDirectDrawSurfaceImpl
*This
,
2752 WINE_GL_BUFFER_TYPE
*buffer_type_p
, D3DRECT
*rect
)
2754 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
2755 WINE_GL_BUFFER_TYPE buffer_type
;
2757 /* First check if we BLT to the backbuffer... */
2758 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) != 0) {
2759 buffer_type
= WINE_GL_BUFFER_BACK
;
2760 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
2761 buffer_type
= WINE_GL_BUFFER_FRONT
;
2763 ERR("Only BLT override to front or back-buffer is supported for now !\n");
2764 return DDERR_INVALIDPARAMS
;
2767 if ((gl_d3d_dev
->state
[buffer_type
] == SURFACE_MEMORY_DIRTY
) &&
2768 (rect
->u1
.x1
>= gl_d3d_dev
->lock_rect
[buffer_type
].left
) &&
2769 (rect
->u2
.y1
>= gl_d3d_dev
->lock_rect
[buffer_type
].top
) &&
2770 (rect
->u3
.x2
<= gl_d3d_dev
->lock_rect
[buffer_type
].right
) &&
2771 (rect
->u4
.y2
<= gl_d3d_dev
->lock_rect
[buffer_type
].bottom
)) {
2772 /* If the memory zone is already dirty, use the standard 'in memory' blit operations and not
2775 return DDERR_INVALIDPARAMS
;
2777 *buffer_type_p
= buffer_type
;
2783 d3ddevice_blt(IDirectDrawSurfaceImpl
*This
, LPRECT rdst
,
2784 LPDIRECTDRAWSURFACE7 src
, LPRECT rsrc
,
2785 DWORD dwFlags
, LPDDBLTFX lpbltfx
)
2787 WINE_GL_BUFFER_TYPE buffer_type
;
2791 rect
.u1
.x1
= rdst
->left
;
2792 rect
.u2
.y1
= rdst
->top
;
2793 rect
.u3
.x2
= rdst
->right
;
2794 rect
.u4
.y2
= rdst
->bottom
;
2798 rect
.u3
.x2
= This
->surface_desc
.dwWidth
;
2799 rect
.u4
.y2
= This
->surface_desc
.dwHeight
;
2802 if (setup_rect_and_surface_for_blt(This
, &buffer_type
, &rect
) != DD_OK
) return DDERR_INVALIDPARAMS
;
2804 if (dwFlags
& DDBLT_COLORFILL
) {
2805 /* This is easy to handle for the D3D Device... */
2809 /* The color as given in the Blt function is in the format of the frame-buffer...
2810 * 'clear' expect it in ARGB format => we need to do some conversion :-)
2812 if (This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_PALETTEINDEXED8
) {
2813 if (This
->palette
) {
2814 color
= ((0xFF000000) |
2815 (This
->palette
->palents
[lpbltfx
->u5
.dwFillColor
].peRed
<< 16) |
2816 (This
->palette
->palents
[lpbltfx
->u5
.dwFillColor
].peGreen
<< 8) |
2817 (This
->palette
->palents
[lpbltfx
->u5
.dwFillColor
].peBlue
));
2821 } else if ((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_RGB
) &&
2822 (((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_ALPHAPIXELS
) == 0) ||
2823 (This
->surface_desc
.u4
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x00000000))) {
2824 if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 16) &&
2825 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0xF800) &&
2826 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x07E0) &&
2827 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x001F)) {
2828 if (lpbltfx
->u5
.dwFillColor
== 0xFFFF) {
2831 color
= ((0xFF000000) |
2832 ((lpbltfx
->u5
.dwFillColor
& 0xF800) << 8) |
2833 ((lpbltfx
->u5
.dwFillColor
& 0x07E0) << 5) |
2834 ((lpbltfx
->u5
.dwFillColor
& 0x001F) << 3));
2836 } else if (((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 32) ||
2837 (This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 24)) &&
2838 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0x00FF0000) &&
2839 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x0000FF00) &&
2840 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x000000FF)) {
2841 color
= 0xFF000000 | lpbltfx
->u5
.dwFillColor
;
2843 ERR("Wrong surface type for BLT override (unknown RGB format) !\n");
2844 return DDERR_INVALIDPARAMS
;
2847 ERR("Wrong surface type for BLT override !\n");
2848 return DDERR_INVALIDPARAMS
;
2851 TRACE(" executing D3D Device override.\n");
2855 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
2856 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
2857 glDrawBuffer(GL_FRONT
);
2859 glDrawBuffer(GL_BACK
);
2861 d3ddevice_clear(This
->d3ddevice
, buffer_type
, 1, &rect
, D3DCLEAR_TARGET
, color
, 0.0, 0x00000000);
2863 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
2864 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
2865 glDrawBuffer(prev_draw
);
2870 } else if ((dwFlags
& (~(DDBLT_KEYSRC
|DDBLT_WAIT
|DDBLT_ASYNC
))) == 0) {
2871 /* Normal blit without any special case... */
2873 /* And which has a SRC surface */
2874 IDirectDrawSurfaceImpl
*src_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, src
);
2876 if ((src_impl
->surface_desc
.ddsCaps
.dwCaps
& DDSCAPS_3DDEVICE
) &&
2877 (src_impl
->d3ddevice
== This
->d3ddevice
) &&
2878 ((dwFlags
& DDBLT_KEYSRC
) == 0)) {
2879 /* Both are 3D devices and using the same GL device and the Blt is without color-keying */
2883 WINE_GL_BUFFER_TYPE src_buffer_type
;
2884 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
2890 src_rect
.u1
.x1
= rsrc
->left
;
2891 src_rect
.u2
.y1
= rsrc
->top
;
2892 src_rect
.u3
.x2
= rsrc
->right
;
2893 src_rect
.u4
.y2
= rsrc
->bottom
;
2897 src_rect
.u3
.x2
= src_impl
->surface_desc
.dwWidth
;
2898 src_rect
.u4
.y2
= src_impl
->surface_desc
.dwHeight
;
2901 width
= src_rect
.u3
.x2
- src_rect
.u1
.x1
;
2902 height
= src_rect
.u4
.y2
- src_rect
.u2
.y1
;
2904 if ((width
!= (rect
.u3
.x2
- rect
.u1
.x1
)) ||
2905 (height
!= (rect
.u4
.y2
- rect
.u2
.y1
))) {
2906 FIXME(" buffer to buffer copy not supported with stretching yet !\n");
2907 return DDERR_INVALIDPARAMS
;
2910 /* First check if we BLT from the backbuffer... */
2911 if ((src_impl
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) != 0) {
2912 src_buffer_type
= WINE_GL_BUFFER_BACK
;
2913 } else if ((src_impl
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
2914 src_buffer_type
= WINE_GL_BUFFER_FRONT
;
2916 ERR("Unexpected case in direct buffer to buffer copy !\n");
2917 return DDERR_INVALIDPARAMS
;
2920 TRACE(" using direct buffer to buffer copy.\n");
2924 opt_bitmap
= d3ddevice_set_state_for_flush(This
->d3ddevice
, (LPCRECT
) &rect
, FALSE
, &initial
);
2926 if (upload_surface_to_tex_memory_init(This
, 0, &gl_d3d_dev
->current_internal_format
,
2927 initial
, FALSE
, UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
2928 ERR(" unsupported pixel format at direct buffer to buffer copy.\n");
2930 return DDERR_INVALIDPARAMS
;
2933 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
2934 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
2935 glDrawBuffer(GL_FRONT
);
2937 glDrawBuffer(GL_BACK
);
2939 if (src_buffer_type
== WINE_GL_BUFFER_FRONT
)
2940 glReadBuffer(GL_FRONT
);
2942 glReadBuffer(GL_BACK
);
2944 /* Now the serious stuff happens. Basically, we copy from the source buffer to the texture memory.
2945 And directly re-draws this on the destination buffer. */
2946 for (y
= 0; y
< height
; y
+= UNLOCK_TEX_SIZE
) {
2949 if ((src_rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
) > src_impl
->surface_desc
.dwHeight
)
2950 get_height
= src_impl
->surface_desc
.dwHeight
- (src_rect
.u2
.y1
+ y
);
2952 get_height
= UNLOCK_TEX_SIZE
;
2954 for (x
= 0; x
< width
; x
+= UNLOCK_TEX_SIZE
) {
2957 if ((src_rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
) > src_impl
->surface_desc
.dwWidth
)
2958 get_width
= src_impl
->surface_desc
.dwWidth
- (src_rect
.u1
.x1
+ x
);
2960 get_width
= UNLOCK_TEX_SIZE
;
2962 glCopyTexSubImage2D(GL_TEXTURE_2D
, 0,
2963 0, UNLOCK_TEX_SIZE
- get_height
,
2964 src_rect
.u1
.x1
+ x
, src_impl
->surface_desc
.dwHeight
- (src_rect
.u2
.y1
+ y
+ get_height
),
2965 get_width
, get_height
);
2968 glTexCoord2f(0.0, 0.0);
2969 glVertex3d(rect
.u1
.x1
+ x
,
2970 rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
,
2972 glTexCoord2f(1.0, 0.0);
2973 glVertex3d(rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
,
2974 rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
,
2976 glTexCoord2f(1.0, 1.0);
2977 glVertex3d(rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
,
2980 glTexCoord2f(0.0, 1.0);
2981 glVertex3d(rect
.u1
.x1
+ x
,
2988 upload_surface_to_tex_memory_release();
2989 d3ddevice_restore_state_after_flush(This
->d3ddevice
, opt_bitmap
, FALSE
);
2991 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
2992 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
2993 glDrawBuffer(prev_draw
);
2999 /* This is the normal 'with source' Blit. Use the texture engine to do the Blt for us
3000 (this prevents calling glReadPixels) */
3004 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
3008 double x_stretch
, y_stretch
;
3011 src_rect
.u1
.x1
= rsrc
->left
;
3012 src_rect
.u2
.y1
= rsrc
->top
;
3013 src_rect
.u3
.x2
= rsrc
->right
;
3014 src_rect
.u4
.y2
= rsrc
->bottom
;
3018 src_rect
.u3
.x2
= src_impl
->surface_desc
.dwWidth
;
3019 src_rect
.u4
.y2
= src_impl
->surface_desc
.dwHeight
;
3022 width
= src_rect
.u3
.x2
- src_rect
.u1
.x1
;
3023 height
= src_rect
.u4
.y2
- src_rect
.u2
.y1
;
3025 x_stretch
= (double) (rect
.u3
.x2
- rect
.u1
.x1
) / (double) width
;
3026 y_stretch
= (double) (rect
.u4
.y2
- rect
.u2
.y1
) / (double) height
;
3028 TRACE(" using memory to buffer Blt overide.\n");
3032 opt_bitmap
= d3ddevice_set_state_for_flush(This
->d3ddevice
, (LPCRECT
) &rect
, ((dwFlags
& DDBLT_KEYSRC
) != 0), &initial
);
3034 if (upload_surface_to_tex_memory_init(src_impl
, 0, &gl_d3d_dev
->current_internal_format
,
3035 initial
, ((dwFlags
& DDBLT_KEYSRC
) != 0), UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
3036 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3038 return DDERR_INVALIDPARAMS
;
3041 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3042 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
3043 glDrawBuffer(GL_FRONT
);
3045 glDrawBuffer(GL_BACK
);
3047 /* Now the serious stuff happens. This is basically the same code that for the memory
3048 flush to frame buffer ... with stretching and different rectangles added :-) */
3049 for (y
= 0; y
< height
; y
+= UNLOCK_TEX_SIZE
) {
3052 flush_rect
.top
= src_rect
.u2
.y1
+ y
;
3053 flush_rect
.bottom
= ((src_rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
> src_rect
.u4
.y2
) ?
3055 (src_rect
.u2
.y1
+ y
+ UNLOCK_TEX_SIZE
));
3057 for (x
= 0; x
< width
; x
+= UNLOCK_TEX_SIZE
) {
3058 flush_rect
.left
= src_rect
.u1
.x1
+ x
;
3059 flush_rect
.right
= ((src_rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
> src_rect
.u3
.x2
) ?
3061 (src_rect
.u1
.x1
+ x
+ UNLOCK_TEX_SIZE
));
3063 upload_surface_to_tex_memory(&flush_rect
, 0, 0, &(gl_d3d_dev
->surface_ptr
));
3066 glTexCoord2f(0.0, 0.0);
3067 glVertex3d(rect
.u1
.x1
+ (x
* x_stretch
),
3068 rect
.u2
.y1
+ (y
* y_stretch
),
3070 glTexCoord2f(1.0, 0.0);
3071 glVertex3d(rect
.u1
.x1
+ ((x
+ UNLOCK_TEX_SIZE
) * x_stretch
),
3072 rect
.u2
.y1
+ (y
* y_stretch
),
3074 glTexCoord2f(1.0, 1.0);
3075 glVertex3d(rect
.u1
.x1
+ ((x
+ UNLOCK_TEX_SIZE
) * x_stretch
),
3076 rect
.u2
.y1
+ ((y
+ UNLOCK_TEX_SIZE
) * y_stretch
),
3078 glTexCoord2f(0.0, 1.0);
3079 glVertex3d(rect
.u1
.x1
+ (x
* x_stretch
),
3080 rect
.u2
.y1
+ ((y
+ UNLOCK_TEX_SIZE
) * y_stretch
),
3086 upload_surface_to_tex_memory_release();
3087 d3ddevice_restore_state_after_flush(This
->d3ddevice
, opt_bitmap
, ((dwFlags
& DDBLT_KEYSRC
) != 0));
3089 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
3090 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
3091 glDrawBuffer(prev_draw
);
3099 return DDERR_INVALIDPARAMS
;
3103 d3ddevice_bltfast(IDirectDrawSurfaceImpl
*This
, DWORD dstx
,
3104 DWORD dsty
, LPDIRECTDRAWSURFACE7 src
,
3105 LPRECT rsrc
, DWORD trans
)
3109 IDirectDrawSurfaceImpl
*src_impl
= ICOM_OBJECT(IDirectDrawSurfaceImpl
, IDirectDrawSurface7
, src
);
3110 IDirect3DDeviceGLImpl
*gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) This
->d3ddevice
;
3111 WINE_GL_BUFFER_TYPE buffer_type
;
3115 int width
, height
, x
, y
;
3117 /* Cannot support DSTCOLORKEY blitting... */
3118 if ((trans
& DDBLTFAST_DESTCOLORKEY
) != 0) return DDERR_INVALIDPARAMS
;
3121 WARN("rsrc is NULL - getting the whole surface !!\n");
3123 rsrc
->left
= rsrc
->top
= 0;
3124 rsrc
->right
= src_impl
->surface_desc
.dwWidth
;
3125 rsrc
->bottom
= src_impl
->surface_desc
.dwHeight
;
3133 rdst
.right
= dstx
+ (rsrc
->right
- rsrc
->left
);
3134 if (rdst
.right
> This
->surface_desc
.dwWidth
) {
3135 rsrc
->right
-= (This
->surface_desc
.dwWidth
- rdst
.right
);
3136 rdst
.right
= This
->surface_desc
.dwWidth
;
3138 rdst
.bottom
= dsty
+ (rsrc
->bottom
- rsrc
->top
);
3139 if (rdst
.bottom
> This
->surface_desc
.dwHeight
) {
3140 rsrc
->bottom
-= (This
->surface_desc
.dwHeight
- rdst
.bottom
);
3141 rdst
.bottom
= This
->surface_desc
.dwHeight
;
3144 width
= rsrc
->right
- rsrc
->left
;
3145 height
= rsrc
->bottom
- rsrc
->top
;
3147 if (setup_rect_and_surface_for_blt(This
, &buffer_type
, (D3DRECT
*) &rdst
) != DD_OK
) return DDERR_INVALIDPARAMS
;
3149 TRACE(" using BltFast memory to frame buffer overide.\n");
3153 opt_bitmap
= d3ddevice_set_state_for_flush(This
->d3ddevice
, &rdst
, (trans
& DDBLTFAST_SRCCOLORKEY
) != 0, &initial
);
3155 if (upload_surface_to_tex_memory_init(src_impl
, 0, &gl_d3d_dev
->current_internal_format
,
3156 initial
, (trans
& DDBLTFAST_SRCCOLORKEY
) != 0,
3157 UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
3158 ERR(" unsupported pixel format at memory to buffer Blt overide.\n");
3160 return DDERR_INVALIDPARAMS
;
3163 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3164 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
3165 glDrawBuffer(GL_FRONT
);
3167 glDrawBuffer(GL_BACK
);
3169 /* Now the serious stuff happens. This is basically the same code that for the memory
3170 flush to frame buffer but with different rectangles for source and destination :-) */
3171 for (y
= 0; y
< height
; y
+= UNLOCK_TEX_SIZE
) {
3174 flush_rect
.top
= rsrc
->top
+ y
;
3175 flush_rect
.bottom
= ((rsrc
->top
+ y
+ UNLOCK_TEX_SIZE
> rsrc
->bottom
) ?
3177 (rsrc
->top
+ y
+ UNLOCK_TEX_SIZE
));
3179 for (x
= 0; x
< width
; x
+= UNLOCK_TEX_SIZE
) {
3180 flush_rect
.left
= rsrc
->left
+ x
;
3181 flush_rect
.right
= ((rsrc
->left
+ x
+ UNLOCK_TEX_SIZE
> rsrc
->right
) ?
3183 (rsrc
->left
+ x
+ UNLOCK_TEX_SIZE
));
3185 upload_surface_to_tex_memory(&flush_rect
, 0, 0, &(gl_d3d_dev
->surface_ptr
));
3188 glTexCoord2f(0.0, 0.0);
3189 glVertex3d(rdst
.left
+ x
,
3192 glTexCoord2f(1.0, 0.0);
3193 glVertex3d(rdst
.left
+ (x
+ UNLOCK_TEX_SIZE
),
3196 glTexCoord2f(1.0, 1.0);
3197 glVertex3d(rdst
.left
+ (x
+ UNLOCK_TEX_SIZE
),
3198 rdst
.top
+ (y
+ UNLOCK_TEX_SIZE
),
3200 glTexCoord2f(0.0, 1.0);
3201 glVertex3d(rdst
.left
+ x
,
3202 rdst
.top
+ (y
+ UNLOCK_TEX_SIZE
),
3208 upload_surface_to_tex_memory_release();
3209 d3ddevice_restore_state_after_flush(This
->d3ddevice
, opt_bitmap
, (trans
& DDBLTFAST_SRCCOLORKEY
) != 0);
3211 if (((buffer_type
== WINE_GL_BUFFER_FRONT
) && (prev_draw
== GL_BACK
)) ||
3212 ((buffer_type
== WINE_GL_BUFFER_BACK
) && (prev_draw
== GL_FRONT
)))
3213 glDrawBuffer(prev_draw
);
3221 d3ddevice_set_ortho(IDirect3DDeviceImpl
*This
)
3223 GLfloat height
, width
;
3224 GLfloat trans_mat
[16];
3226 TRACE("(%p)\n", This
);
3228 width
= This
->surface
->surface_desc
.dwWidth
;
3229 height
= This
->surface
->surface_desc
.dwHeight
;
3231 /* The X axis is straighforward.. For the Y axis, we need to convert 'D3D' screen coordinates
3232 to OpenGL screen coordinates (ie the upper left corner is not the same).
3233 For Z, the mystery is what should it be mapped to ? Ie should the resulting range be between
3234 -1.0 and 1.0 (as the X and Y coordinates) or between 0.0 and 1.0 ? */
3235 trans_mat
[ 0] = 2.0 / width
; trans_mat
[ 4] = 0.0; trans_mat
[ 8] = 0.0; trans_mat
[12] = -1.0;
3236 trans_mat
[ 1] = 0.0; trans_mat
[ 5] = -2.0 / height
; trans_mat
[ 9] = 0.0; trans_mat
[13] = 1.0;
3237 trans_mat
[ 2] = 0.0; trans_mat
[ 6] = 0.0; trans_mat
[10] = 2.0; trans_mat
[14] = -1.0;
3238 trans_mat
[ 3] = 0.0; trans_mat
[ 7] = 0.0; trans_mat
[11] = 0.0; trans_mat
[15] = 1.0;
3241 glMatrixMode(GL_MODELVIEW
);
3243 /* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
3244 Correctness Tips section).
3246 Basically, from what I understood, if the game does not filter the font texture,
3247 as the 'real' pixel will lie at the middle of the two texels, OpenGL may choose the wrong
3248 one and we will have strange artifacts (as the rounding and stuff may give different results
3249 for different pixels, ie sometimes take the left pixel, sometimes the right).
3251 glTranslatef(0.375, 0.375, 0);
3252 glMatrixMode(GL_PROJECTION
);
3253 glLoadMatrixf(trans_mat
);
3258 d3ddevice_set_matrices(IDirect3DDeviceImpl
*This
, DWORD matrices
,
3259 D3DMATRIX
*world_mat
, D3DMATRIX
*view_mat
, D3DMATRIX
*proj_mat
)
3261 TRACE("(%p,%08lx,%p,%p,%p)\n", This
, matrices
, world_mat
, view_mat
, proj_mat
);
3264 if ((matrices
& (VIEWMAT_CHANGED
|WORLDMAT_CHANGED
)) != 0) {
3265 glMatrixMode(GL_MODELVIEW
);
3266 glLoadMatrixf((float *) view_mat
);
3268 /* Now also re-loads all the Lights and Clipping Planes using the new matrices */
3269 if (This
->state_block
.render_state
[D3DRENDERSTATE_CLIPPING
- 1] != FALSE
) {
3272 for (i
= 0, runner
= 0x00000001; i
< This
->max_clipping_planes
; i
++, runner
<<= 1) {
3273 if (runner
& This
->state_block
.render_state
[D3DRENDERSTATE_CLIPPLANEENABLE
- 1]) {
3276 plane
[0] = This
->clipping_planes
[i
].plane
[0];
3277 plane
[1] = This
->clipping_planes
[i
].plane
[1];
3278 plane
[2] = This
->clipping_planes
[i
].plane
[2];
3279 plane
[3] = This
->clipping_planes
[i
].plane
[3];
3281 glClipPlane( GL_CLIP_PLANE0
+ i
, (const GLdouble
*) (&plane
) );
3285 if (This
->state_block
.render_state
[D3DRENDERSTATE_LIGHTING
- 1] != FALSE
) {
3289 for (i
= 0, runner
= 0x00000001; i
< MAX_LIGHTS
; i
++, runner
<<= 1) {
3290 if (runner
& This
->active_lights
) {
3291 switch (This
->light_parameters
[i
].dltType
) {
3292 case D3DLIGHT_DIRECTIONAL
: {
3294 float cut_off
= 180.0;
3296 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
3297 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
3298 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
3299 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
3301 direction
[0] = This
->light_parameters
[i
].dvDirection
.u1
.x
;
3302 direction
[1] = This
->light_parameters
[i
].dvDirection
.u2
.y
;
3303 direction
[2] = This
->light_parameters
[i
].dvDirection
.u3
.z
;
3305 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) direction
);
3308 case D3DLIGHT_POINT
: {
3310 float cut_off
= 180.0;
3312 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
3313 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
3314 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
3315 position
[0] = This
->light_parameters
[i
].dvPosition
.u1
.x
;
3316 position
[1] = This
->light_parameters
[i
].dvPosition
.u2
.y
;
3317 position
[2] = This
->light_parameters
[i
].dvPosition
.u3
.z
;
3319 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) position
);
3320 glLightfv(GL_LIGHT0
+ i
, GL_CONSTANT_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation0
));
3321 glLightfv(GL_LIGHT0
+ i
, GL_LINEAR_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation1
));
3322 glLightfv(GL_LIGHT0
+ i
, GL_QUADRATIC_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation2
));
3323 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
3326 case D3DLIGHT_SPOT
: {
3329 float cut_off
= 90.0 * (This
->light_parameters
[i
].dvPhi
/ M_PI
);
3331 glLightfv(GL_LIGHT0
+ i
, GL_AMBIENT
, (float *) &(This
->light_parameters
[i
].dcvAmbient
));
3332 glLightfv(GL_LIGHT0
+ i
, GL_DIFFUSE
, (float *) &(This
->light_parameters
[i
].dcvDiffuse
));
3333 glLightfv(GL_LIGHT0
+ i
, GL_SPECULAR
, (float *) &(This
->light_parameters
[i
].dcvSpecular
));
3335 direction
[0] = This
->light_parameters
[i
].dvDirection
.u1
.x
;
3336 direction
[1] = This
->light_parameters
[i
].dvDirection
.u2
.y
;
3337 direction
[2] = This
->light_parameters
[i
].dvDirection
.u3
.z
;
3339 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_DIRECTION
, (float *) direction
);
3340 position
[0] = This
->light_parameters
[i
].dvPosition
.u1
.x
;
3341 position
[1] = This
->light_parameters
[i
].dvPosition
.u2
.y
;
3342 position
[2] = This
->light_parameters
[i
].dvPosition
.u3
.z
;
3344 glLightfv(GL_LIGHT0
+ i
, GL_POSITION
, (float *) position
);
3345 glLightfv(GL_LIGHT0
+ i
, GL_CONSTANT_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation0
));
3346 glLightfv(GL_LIGHT0
+ i
, GL_LINEAR_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation1
));
3347 glLightfv(GL_LIGHT0
+ i
, GL_QUADRATIC_ATTENUATION
, &(This
->light_parameters
[i
].dvAttenuation2
));
3348 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_CUTOFF
, &cut_off
);
3349 glLightfv(GL_LIGHT0
+ i
, GL_SPOT_EXPONENT
, &(This
->light_parameters
[i
].dvFalloff
));
3353 /* No warning here as it's already done at light setting */
3360 glMultMatrixf((float *) world_mat
);
3362 if ((matrices
& PROJMAT_CHANGED
) != 0) {
3363 glMatrixMode(GL_PROJECTION
);
3364 glLoadMatrixf((float *) proj_mat
);
3370 d3ddevice_matrices_updated(IDirect3DDeviceImpl
*This
, DWORD matrices
)
3372 IDirect3DDeviceGLImpl
*glThis
= (IDirect3DDeviceGLImpl
*) This
;
3373 DWORD tex_mat
, tex_stage
;
3375 TRACE("(%p,%08lx)\n", This
, matrices
);
3377 if (matrices
& (VIEWMAT_CHANGED
|WORLDMAT_CHANGED
|PROJMAT_CHANGED
)) {
3378 if (glThis
->transform_state
== GL_TRANSFORM_NORMAL
) {
3379 /* This will force an update of the transform state at the next drawing. */
3380 glThis
->transform_state
= GL_TRANSFORM_NONE
;
3383 if (matrices
& (TEXMAT0_CHANGED
|TEXMAT1_CHANGED
|TEXMAT2_CHANGED
|TEXMAT3_CHANGED
|
3384 TEXMAT4_CHANGED
|TEXMAT5_CHANGED
|TEXMAT6_CHANGED
|TEXMAT7_CHANGED
))
3387 for (tex_mat
= TEXMAT0_CHANGED
, tex_stage
= 0; tex_mat
<= TEXMAT7_CHANGED
; tex_mat
<<= 1, tex_stage
++) {
3388 GLenum unit
= GL_TEXTURE0_WINE
+ tex_stage
;
3389 if (matrices
& tex_mat
) {
3390 if (This
->state_block
.texture_stage_state
[tex_stage
][D3DTSS_TEXTURETRANSFORMFLAGS
- 1] != D3DTTFF_DISABLE
) {
3391 int is_identity
= (memcmp(This
->tex_mat
[tex_stage
], id_mat
, 16 * sizeof(D3DVALUE
)) != 0);
3393 if (This
->tex_mat_is_identity
[tex_stage
] != is_identity
) {
3394 if (glThis
->current_active_tex_unit
!= unit
) {
3395 GL_extensions
.glActiveTexture(unit
);
3396 glThis
->current_active_tex_unit
= unit
;
3398 glMatrixMode(GL_TEXTURE
);
3399 glLoadMatrixf((float *) This
->tex_mat
[tex_stage
]);
3401 This
->tex_mat_is_identity
[tex_stage
] = is_identity
;
3403 if (This
->tex_mat_is_identity
[tex_stage
] == FALSE
) {
3404 if (glThis
->current_active_tex_unit
!= unit
) {
3405 GL_extensions
.glActiveTexture(unit
);
3406 glThis
->current_active_tex_unit
= unit
;
3408 glMatrixMode(GL_TEXTURE
);
3410 This
->tex_mat_is_identity
[tex_stage
] = TRUE
;
3419 /* TODO for both these functions :
3420 - change / restore OpenGL parameters for pictures transfers in case they are ever modified
3421 by other OpenGL code in D3D
3422 - handle the case where no 'Begin / EndScene' was done between two locks
3423 - handle the rectangles in the unlock too
3424 - handle pitch correctly...
3426 static void d3ddevice_lock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
, DWORD dwFlags
)
3428 IDirect3DDeviceImpl
*d3d_dev
= This
->d3ddevice
;
3429 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
3430 WINE_GL_BUFFER_TYPE buffer_type
;
3433 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
3434 buffer_type
= WINE_GL_BUFFER_FRONT
;
3435 if ((gl_d3d_dev
->state
[WINE_GL_BUFFER_FRONT
] != SURFACE_GL
) &&
3436 (gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_FRONT
] != This
)) {
3437 ERR("Change of front buffer.. Expect graphic corruptions !\n");
3439 gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_FRONT
] = This
;
3440 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) == (DDSCAPS_BACKBUFFER
)) {
3441 buffer_type
= WINE_GL_BUFFER_BACK
;
3442 if ((gl_d3d_dev
->state
[WINE_GL_BUFFER_BACK
] != SURFACE_GL
) &&
3443 (gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_BACK
] != This
)) {
3444 ERR("Change of back buffer.. Expect graphic corruptions !\n");
3446 gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_BACK
] = This
;
3448 ERR("Wrong surface type for locking !\n");
3452 if (pRect
== NULL
) {
3455 loc_rect
.bottom
= This
->surface_desc
.dwHeight
;
3456 loc_rect
.right
= This
->surface_desc
.dwWidth
;
3460 /* Try to acquire the device critical section */
3461 EnterCriticalSection(&(d3d_dev
->crit
));
3463 if (gl_d3d_dev
->lock_rect_valid
[buffer_type
] == TRUE
) {
3464 ERR("Two consecutive locks on %s buffer... Expect problems !\n",
3465 (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"));
3467 gl_d3d_dev
->lock_rect_valid
[buffer_type
] = TRUE
;
3469 if (gl_d3d_dev
->state
[buffer_type
] != SURFACE_GL
) {
3470 /* Check if the new rectangle is in the previous one or not.
3471 If it is not, flush first the previous locks on screen.
3473 if ((pRect
->top
< gl_d3d_dev
->lock_rect
[buffer_type
].top
) ||
3474 (pRect
->left
< gl_d3d_dev
->lock_rect
[buffer_type
].left
) ||
3475 (pRect
->right
> gl_d3d_dev
->lock_rect
[buffer_type
].right
) ||
3476 (pRect
->bottom
> gl_d3d_dev
->lock_rect
[buffer_type
].bottom
)) {
3477 if (gl_d3d_dev
->state
[buffer_type
] == SURFACE_MEMORY_DIRTY
) {
3478 TRACE(" flushing back to %s buffer as new rect : (%ldx%ld) - (%ldx%ld) not included in old rect : (%ldx%ld) - (%ldx%ld)\n",
3479 (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"),
3480 pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
,
3481 gl_d3d_dev
->lock_rect
[buffer_type
].left
, gl_d3d_dev
->lock_rect
[buffer_type
].top
,
3482 gl_d3d_dev
->lock_rect
[buffer_type
].right
, gl_d3d_dev
->lock_rect
[buffer_type
].bottom
);
3483 d3d_dev
->flush_to_framebuffer(d3d_dev
, &(gl_d3d_dev
->lock_rect
[buffer_type
]), gl_d3d_dev
->lock_surf
[buffer_type
]);
3485 gl_d3d_dev
->state
[buffer_type
] = SURFACE_GL
;
3486 gl_d3d_dev
->lock_rect
[buffer_type
] = *pRect
;
3488 /* In the other case, do not upgrade the locking rectangle as it's no need... */
3490 gl_d3d_dev
->lock_rect
[buffer_type
] = *pRect
;
3493 if (gl_d3d_dev
->state
[buffer_type
] == SURFACE_GL
) {
3494 /* If the surface is already in memory, no need to do anything here... */
3495 GLenum buffer_format
;
3496 GLenum buffer_color
;
3500 TRACE(" copying %s buffer to main memory with rectangle (%ldx%ld) - (%ldx%ld).\n", (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"),
3501 pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
3503 /* Note that here we cannot do 'optmizations' about the WriteOnly flag... Indeed, a game
3504 may only write to the device... But when we will blit it back to the screen, we need
3505 also to blit correctly the parts the application did not overwrite... */
3507 if (((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_RGB
) != 0) &&
3508 (((This
->surface_desc
.u4
.ddpfPixelFormat
.dwFlags
& DDPF_ALPHAPIXELS
) == 0) ||
3509 (This
->surface_desc
.u4
.ddpfPixelFormat
.u5
.dwRGBAlphaBitMask
== 0x00000000))) {
3510 if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 16) &&
3511 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0xF800) &&
3512 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x07E0) &&
3513 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x001F)) {
3514 buffer_format
= GL_UNSIGNED_SHORT_5_6_5
;
3515 buffer_color
= GL_RGB
;
3516 } else if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 24) &&
3517 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0xFF0000) &&
3518 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x00FF00) &&
3519 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x0000FF)) {
3520 buffer_format
= GL_UNSIGNED_BYTE
;
3521 buffer_color
= GL_RGB
;
3522 } else if ((This
->surface_desc
.u4
.ddpfPixelFormat
.u1
.dwRGBBitCount
== 32) &&
3523 (This
->surface_desc
.u4
.ddpfPixelFormat
.u2
.dwRBitMask
== 0x00FF0000) &&
3524 (This
->surface_desc
.u4
.ddpfPixelFormat
.u3
.dwGBitMask
== 0x0000FF00) &&
3525 (This
->surface_desc
.u4
.ddpfPixelFormat
.u4
.dwBBitMask
== 0x000000FF)) {
3526 buffer_format
= GL_UNSIGNED_INT_8_8_8_8_REV
;
3527 buffer_color
= GL_BGRA
;
3529 ERR(" unsupported pixel format at device locking.\n");
3533 ERR(" unsupported pixel format at device locking - alpha on frame buffer.\n");
3539 if (buffer_type
== WINE_GL_BUFFER_FRONT
)
3540 /* Application wants to lock the front buffer */
3541 glReadBuffer(GL_FRONT
);
3543 /* Application wants to lock the back buffer */
3544 glReadBuffer(GL_BACK
);
3546 dst
= ((char *)This
->surface_desc
.lpSurface
) +
3547 (pRect
->top
* This
->surface_desc
.u1
.lPitch
) + (pRect
->left
* GET_BPP(This
->surface_desc
));
3548 for (y
= (This
->surface_desc
.dwHeight
- pRect
->top
- 1);
3549 y
>= ((int) This
->surface_desc
.dwHeight
- (int) pRect
->bottom
);
3551 glReadPixels(pRect
->left
, y
,
3552 pRect
->right
- pRect
->left
, 1,
3553 buffer_color
, buffer_format
, dst
);
3554 dst
+= This
->surface_desc
.u1
.lPitch
;
3557 gl_d3d_dev
->state
[buffer_type
] = SURFACE_MEMORY
;
3560 /* I keep this code here as it's very useful to debug :-) */
3562 static int flush_count
= 0;
3566 if ((++flush_count
% 50) == 0) {
3567 sprintf(buf
, "lock_%06d.pnm", flush_count
);
3568 f
= fopen(buf
, "wb");
3569 DDRAW_dump_surface_to_disk(This
, f
);
3578 static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl
*d3d_dev
, LPCRECT pRect
, IDirectDrawSurfaceImpl
*surf
) {
3580 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
3585 /* Note : no need here to lock the 'device critical section' as we are already protected by
3586 the GL critical section. */
3588 if (pRect
== NULL
) {
3591 loc_rect
.bottom
= d3d_dev
->surface
->surface_desc
.dwHeight
;
3592 loc_rect
.right
= d3d_dev
->surface
->surface_desc
.dwWidth
;
3596 TRACE(" flushing memory back to screen memory (%ld,%ld) x (%ld,%ld).\n", pRect
->top
, pRect
->left
, pRect
->right
, pRect
->bottom
);
3598 opt_bitmap
= d3ddevice_set_state_for_flush(d3d_dev
, pRect
, FALSE
, &initial
);
3600 if (upload_surface_to_tex_memory_init(surf
, 0, &gl_d3d_dev
->current_internal_format
,
3601 initial
, FALSE
, UNLOCK_TEX_SIZE
, UNLOCK_TEX_SIZE
) != DD_OK
) {
3602 ERR(" unsupported pixel format at frame buffer flush.\n");
3606 for (y
= pRect
->top
; y
< pRect
->bottom
; y
+= UNLOCK_TEX_SIZE
) {
3610 flush_rect
.bottom
= (y
+ UNLOCK_TEX_SIZE
> pRect
->bottom
) ? pRect
->bottom
: (y
+ UNLOCK_TEX_SIZE
);
3612 for (x
= pRect
->left
; x
< pRect
->right
; x
+= UNLOCK_TEX_SIZE
) {
3613 /* First, upload the texture... */
3614 flush_rect
.left
= x
;
3615 flush_rect
.right
= (x
+ UNLOCK_TEX_SIZE
> pRect
->right
) ? pRect
->right
: (x
+ UNLOCK_TEX_SIZE
);
3617 upload_surface_to_tex_memory(&flush_rect
, 0, 0, &(gl_d3d_dev
->surface_ptr
));
3620 glTexCoord2f(0.0, 0.0);
3621 glVertex3d(x
, y
, 0.5);
3622 glTexCoord2f(1.0, 0.0);
3623 glVertex3d(x
+ UNLOCK_TEX_SIZE
, y
, 0.5);
3624 glTexCoord2f(1.0, 1.0);
3625 glVertex3d(x
+ UNLOCK_TEX_SIZE
, y
+ UNLOCK_TEX_SIZE
, 0.5);
3626 glTexCoord2f(0.0, 1.0);
3627 glVertex3d(x
, y
+ UNLOCK_TEX_SIZE
, 0.5);
3632 upload_surface_to_tex_memory_release();
3633 d3ddevice_restore_state_after_flush(d3d_dev
, opt_bitmap
, FALSE
);
3636 /* I keep this code here as it's very useful to debug :-) */
3638 static int flush_count
= 0;
3642 if ((++flush_count
% 50) == 0) {
3643 sprintf(buf
, "flush_%06d.pnm", flush_count
);
3644 f
= fopen(buf
, "wb");
3645 DDRAW_dump_surface_to_disk(surf
, f
);
3651 static void d3ddevice_unlock_update(IDirectDrawSurfaceImpl
* This
, LPCRECT pRect
)
3653 WINE_GL_BUFFER_TYPE buffer_type
;
3654 IDirect3DDeviceImpl
*d3d_dev
= This
->d3ddevice
;
3655 IDirect3DDeviceGLImpl
* gl_d3d_dev
= (IDirect3DDeviceGLImpl
*) d3d_dev
;
3657 if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_FRONTBUFFER
|DDSCAPS_PRIMARYSURFACE
)) != 0) {
3658 buffer_type
= WINE_GL_BUFFER_FRONT
;
3659 } else if ((This
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_BACKBUFFER
)) == (DDSCAPS_BACKBUFFER
)) {
3660 buffer_type
= WINE_GL_BUFFER_BACK
;
3662 ERR("Wrong surface type for locking !\n");
3666 if (gl_d3d_dev
->lock_rect_valid
[buffer_type
] == FALSE
) {
3667 ERR("Unlock without prior lock on %s buffer... Expect problems !\n",
3668 (buffer_type
== WINE_GL_BUFFER_BACK
? "back" : "front"));
3670 gl_d3d_dev
->lock_rect_valid
[buffer_type
] = FALSE
;
3672 /* First, check if we need to do anything. For the backbuffer, flushing is done at the next 3D activity. */
3673 if ((This
->lastlocktype
& DDLOCK_READONLY
) == 0) {
3674 if (buffer_type
== WINE_GL_BUFFER_FRONT
) {
3677 TRACE(" flushing front buffer immediatly on screen.\n");
3680 glGetIntegerv(GL_DRAW_BUFFER
, &prev_draw
);
3681 glDrawBuffer(GL_FRONT
);
3682 /* Note: we do not use the application provided lock rectangle but our own stored at
3683 lock time. This is because in old D3D versions, the 'lock' parameter did not
3686 d3d_dev
->flush_to_framebuffer(d3d_dev
, &(gl_d3d_dev
->lock_rect
[WINE_GL_BUFFER_FRONT
]), gl_d3d_dev
->lock_surf
[WINE_GL_BUFFER_FRONT
]);
3687 glDrawBuffer(prev_draw
);
3690 gl_d3d_dev
->state
[WINE_GL_BUFFER_BACK
] = SURFACE_MEMORY_DIRTY
;
3694 /* And 'frees' the device critical section */
3695 LeaveCriticalSection(&(d3d_dev
->crit
));
3699 apply_texture_state(IDirect3DDeviceImpl
*This
)
3703 /* Initialize texture stages states */
3704 for (stage
= 0; stage
< MAX_TEXTURES
; stage
++) {
3705 for (state
= 0; state
< HIGHEST_TEXTURE_STAGE_STATE
; state
+= 1) {
3706 if (This
->state_block
.set_flags
.texture_stage_state
[stage
][state
] == TRUE
) {
3707 IDirect3DDevice7_SetTextureStageState(ICOM_INTERFACE(This
, IDirect3DDevice7
),
3708 stage
, state
+ 1, This
->state_block
.texture_stage_state
[stage
][state
]);
3715 d3ddevice_create(IDirect3DDeviceImpl
**obj
, IDirectDrawImpl
*d3d
, IDirectDrawSurfaceImpl
*surface
)
3717 IDirect3DDeviceImpl
*object
;
3718 IDirect3DDeviceGLImpl
*gl_object
;
3719 IDirectDrawSurfaceImpl
*surf
;
3724 XVisualInfo
template;
3725 GLenum buffer
= GL_FRONT
;
3728 object
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, sizeof(IDirect3DDeviceGLImpl
));
3729 if (object
== NULL
) return DDERR_OUTOFMEMORY
;
3731 gl_object
= (IDirect3DDeviceGLImpl
*) object
;
3735 object
->surface
= surface
;
3736 object
->set_context
= set_context
;
3737 object
->clear
= d3ddevice_clear_back
;
3738 object
->set_matrices
= d3ddevice_set_matrices
;
3739 object
->matrices_updated
= d3ddevice_matrices_updated
;
3740 object
->flush_to_framebuffer
= d3ddevice_flush_to_frame_buffer
;
3742 TRACE(" creating OpenGL device for surface = %p, d3d = %p\n", surface
, d3d
);
3744 InitializeCriticalSection(&(object
->crit
));
3746 TRACE(" device critical section : %p\n", &(object
->crit
));
3748 device_context
= GetDC(surface
->ddraw_owner
->window
);
3749 gl_object
->display
= get_display(device_context
);
3750 gl_object
->drawable
= get_drawable(device_context
);
3751 ReleaseDC(surface
->ddraw_owner
->window
,device_context
);
3754 template.visualid
= (VisualID
)GetPropA( GetDesktopWindow(), "__wine_x11_visual_id" );
3755 vis
= XGetVisualInfo(gl_object
->display
, VisualIDMask
, &template, &num
);
3757 HeapFree(GetProcessHeap(), 0, object
);
3758 ERR("No visual found !\n");
3760 return DDERR_INVALIDPARAMS
;
3762 TRACE(" visual found\n");
3765 gl_object
->gl_context
= glXCreateContext(gl_object
->display
, vis
,
3768 if (gl_object
->gl_context
== NULL
) {
3769 HeapFree(GetProcessHeap(), 0, object
);
3770 ERR("Error in context creation !\n");
3772 return DDERR_INVALIDPARAMS
;
3774 TRACE(" context created (%p)\n", gl_object
->gl_context
);
3777 /* Look for the front buffer and override its surface's Flip method (if in double buffering) */
3778 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
3779 if ((surf
->surface_desc
.ddsCaps
.dwCaps
&(DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) == (DDSCAPS_FLIP
|DDSCAPS_FRONTBUFFER
)) {
3780 surf
->aux_ctx
= (LPVOID
) object
;
3781 surf
->aux_data
= (LPVOID
) gl_object
->drawable
;
3782 surf
->aux_flip
= opengl_flip
;
3787 /* We are not doing any double buffering.. Then force OpenGL to draw on the front buffer */
3789 TRACE(" no double buffering : drawing on the front buffer\n");
3793 for (surf
= surface
; surf
!= NULL
; surf
= surf
->surface_owner
) {
3794 IDirectDrawSurfaceImpl
*surf2
;
3795 for (surf2
= surf
; surf2
->prev_attached
!= NULL
; surf2
= surf2
->prev_attached
) ;
3796 for (; surf2
!= NULL
; surf2
= surf2
->next_attached
) {
3797 TRACE(" checking surface %p :", surf2
);
3798 if (((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_3DDEVICE
)) == (DDSCAPS_3DDEVICE
)) &&
3799 ((surf2
->surface_desc
.ddsCaps
.dwCaps
& (DDSCAPS_ZBUFFER
)) != (DDSCAPS_ZBUFFER
))) {
3800 /* Override the Lock / Unlock function for all these surfaces */
3801 surf2
->lock_update_prev
= surf2
->lock_update
;
3802 surf2
->lock_update
= d3ddevice_lock_update
;
3803 surf2
->unlock_update_prev
= surf2
->unlock_update
;
3804 surf2
->unlock_update
= d3ddevice_unlock_update
;
3805 /* And install also the blt / bltfast overrides */
3806 surf2
->aux_blt
= d3ddevice_blt
;
3807 surf2
->aux_bltfast
= d3ddevice_bltfast
;
3809 TRACE(" overiding direct surface access.\n");
3811 TRACE(" no overide.\n");
3813 surf2
->d3ddevice
= object
;
3817 /* Set the various light parameters */
3818 for (light
= 0; light
< MAX_LIGHTS
; light
++) {
3819 /* Only set the fields that are not zero-created */
3820 object
->light_parameters
[light
].dltType
= D3DLIGHT_DIRECTIONAL
;
3821 object
->light_parameters
[light
].dcvDiffuse
.u1
.r
= 1.0;
3822 object
->light_parameters
[light
].dcvDiffuse
.u2
.g
= 1.0;
3823 object
->light_parameters
[light
].dcvDiffuse
.u3
.b
= 1.0;
3824 object
->light_parameters
[light
].dvDirection
.u3
.z
= 1.0;
3827 /* Allocate memory for the matrices */
3828 object
->world_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
3829 object
->view_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
3830 object
->proj_mat
= (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
3831 memcpy(object
->world_mat
, id_mat
, 16 * sizeof(float));
3832 memcpy(object
->view_mat
, id_mat
, 16 * sizeof(float));
3833 memcpy(object
->proj_mat
, id_mat
, 16 * sizeof(float));
3834 for (tex_num
= 0; tex_num
< MAX_TEXTURES
; tex_num
++) {
3835 object
->tex_mat
[tex_num
] = (D3DMATRIX
*) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, 16 * sizeof(float));
3836 memcpy(object
->tex_mat
[tex_num
], id_mat
, 16 * sizeof(float));
3837 object
->tex_mat_is_identity
[tex_num
] = TRUE
;
3840 /* Initialisation */
3841 TRACE(" setting current context\n");
3842 object
->set_context(object
);
3843 TRACE(" current context set\n");
3845 /* allocate the clipping planes */
3846 object
->max_clipping_planes
= opengl_device_caps
.wMaxUserClipPlanes
;
3847 object
->clipping_planes
= (d3d7clippingplane
*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, object
->max_clipping_planes
* sizeof(d3d7clippingplane
));
3849 glHint(GL_FOG_HINT
,GL_NICEST
);
3851 /* Initialize the various GL contexts to be in sync with what we store locally */
3854 glClearColor(0.0, 0.0, 0.0, 0.0);
3855 glDepthMask(GL_TRUE
);
3856 gl_object
->depth_mask
= TRUE
;
3857 glEnable(GL_DEPTH_TEST
);
3858 gl_object
->depth_test
= TRUE
;
3859 glDisable(GL_ALPHA_TEST
);
3860 glDisable(GL_STENCIL_TEST
);
3861 glDisable(GL_CULL_FACE
);
3862 glDisable(GL_LIGHTING
);
3863 glDisable(GL_BLEND
);
3865 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_REPLACE
);
3866 gl_object
->current_tex_env
= GL_REPLACE
;
3867 gl_object
->current_active_tex_unit
= GL_TEXTURE0_WINE
;
3868 if (GL_extensions
.glActiveTexture
!= NULL
) {
3869 GL_extensions
.glActiveTexture(GL_TEXTURE0_WINE
);
3872 glClear(GL_COLOR_BUFFER_BIT
| GL_DEPTH_BUFFER_BIT
| GL_STENCIL_BUFFER_BIT
);
3873 glDrawBuffer(buffer
);
3874 glReadBuffer(buffer
);
3875 /* glDisable(GL_DEPTH_TEST); Need here to check for the presence of a ZBuffer and to reenable it when the ZBuffer is attached */
3878 gl_object
->state
[WINE_GL_BUFFER_BACK
] = SURFACE_GL
;
3879 gl_object
->state
[WINE_GL_BUFFER_FRONT
] = SURFACE_GL
;
3881 /* fill_device_capabilities(d3d->ddraw); */
3883 ICOM_INIT_INTERFACE(object
, IDirect3DDevice
, VTABLE_IDirect3DDevice
);
3884 ICOM_INIT_INTERFACE(object
, IDirect3DDevice2
, VTABLE_IDirect3DDevice2
);
3885 ICOM_INIT_INTERFACE(object
, IDirect3DDevice3
, VTABLE_IDirect3DDevice3
);
3886 ICOM_INIT_INTERFACE(object
, IDirect3DDevice7
, VTABLE_IDirect3DDevice7
);
3890 TRACE(" creating implementation at %p.\n", *obj
);
3892 /* And finally warn D3D that this device is now present */
3893 object
->d3d
->d3d_added_device(object
->d3d
, object
);
3895 /* FIXME: Should handle other versions than just 7 */
3896 InitDefaultStateBlock(&object
->state_block
, 7);
3897 /* Apply default render state and texture stage state values */
3898 apply_render_state(object
, &object
->state_block
);
3899 apply_texture_state(object
);
3901 /* And fill the fog table with the default fog value */
3902 build_fog_table(gl_object
->fog_table
, object
->state_block
.render_state
[D3DRENDERSTATE_FOGCOLOR
- 1]);
3907 static void fill_opengl_primcaps(D3DPRIMCAPS
*pc
)
3909 pc
->dwSize
= sizeof(*pc
);
3910 pc
->dwMiscCaps
= D3DPMISCCAPS_CONFORMANT
| D3DPMISCCAPS_CULLCCW
| D3DPMISCCAPS_CULLCW
|
3911 D3DPMISCCAPS_LINEPATTERNREP
| D3DPMISCCAPS_MASKPLANES
| D3DPMISCCAPS_MASKZ
;
3912 pc
->dwRasterCaps
= D3DPRASTERCAPS_DITHER
| D3DPRASTERCAPS_FOGRANGE
| D3DPRASTERCAPS_FOGTABLE
|
3913 D3DPRASTERCAPS_FOGVERTEX
| D3DPRASTERCAPS_STIPPLE
| D3DPRASTERCAPS_ZBIAS
| D3DPRASTERCAPS_ZTEST
| D3DPRASTERCAPS_SUBPIXEL
|
3914 D3DPRASTERCAPS_ZFOG
;
3915 if (GL_extensions
.mipmap_lodbias
== TRUE
) {
3916 pc
->dwRasterCaps
|= D3DPRASTERCAPS_MIPMAPLODBIAS
;
3918 pc
->dwZCmpCaps
= D3DPCMPCAPS_ALWAYS
| D3DPCMPCAPS_EQUAL
| D3DPCMPCAPS_GREATER
| D3DPCMPCAPS_GREATEREQUAL
|
3919 D3DPCMPCAPS_LESS
| D3DPCMPCAPS_LESSEQUAL
| D3DPCMPCAPS_NEVER
| D3DPCMPCAPS_NOTEQUAL
;
3920 pc
->dwSrcBlendCaps
= D3DPBLENDCAPS_ZERO
| D3DPBLENDCAPS_ONE
| D3DPBLENDCAPS_DESTCOLOR
| D3DPBLENDCAPS_INVDESTCOLOR
|
3921 D3DPBLENDCAPS_SRCALPHA
| D3DPBLENDCAPS_INVSRCALPHA
| D3DPBLENDCAPS_DESTALPHA
| D3DPBLENDCAPS_INVDESTALPHA
| D3DPBLENDCAPS_SRCALPHASAT
|
3922 D3DPBLENDCAPS_BOTHSRCALPHA
| D3DPBLENDCAPS_BOTHINVSRCALPHA
;
3923 pc
->dwDestBlendCaps
= D3DPBLENDCAPS_ZERO
| D3DPBLENDCAPS_ONE
| D3DPBLENDCAPS_SRCCOLOR
| D3DPBLENDCAPS_INVSRCCOLOR
|
3924 D3DPBLENDCAPS_SRCALPHA
| D3DPBLENDCAPS_INVSRCALPHA
| D3DPBLENDCAPS_DESTALPHA
| D3DPBLENDCAPS_INVDESTALPHA
| D3DPBLENDCAPS_SRCALPHASAT
|
3925 D3DPBLENDCAPS_BOTHSRCALPHA
| D3DPBLENDCAPS_BOTHINVSRCALPHA
;
3926 pc
->dwAlphaCmpCaps
= D3DPCMPCAPS_ALWAYS
| D3DPCMPCAPS_EQUAL
| D3DPCMPCAPS_GREATER
| D3DPCMPCAPS_GREATEREQUAL
|
3927 D3DPCMPCAPS_LESS
| D3DPCMPCAPS_LESSEQUAL
| D3DPCMPCAPS_NEVER
| D3DPCMPCAPS_NOTEQUAL
;
3928 pc
->dwShadeCaps
= D3DPSHADECAPS_ALPHAFLATBLEND
| D3DPSHADECAPS_ALPHAGOURAUDBLEND
| D3DPSHADECAPS_COLORFLATRGB
| D3DPSHADECAPS_COLORGOURAUDRGB
|
3929 D3DPSHADECAPS_FOGFLAT
| D3DPSHADECAPS_FOGGOURAUD
| D3DPSHADECAPS_SPECULARFLATRGB
| D3DPSHADECAPS_SPECULARGOURAUDRGB
;
3930 pc
->dwTextureCaps
= D3DPTEXTURECAPS_ALPHA
| D3DPTEXTURECAPS_ALPHAPALETTE
| D3DPTEXTURECAPS_BORDER
| D3DPTEXTURECAPS_PERSPECTIVE
|
3931 D3DPTEXTURECAPS_POW2
| D3DPTEXTURECAPS_TRANSPARENCY
;
3932 pc
->dwTextureFilterCaps
= D3DPTFILTERCAPS_LINEAR
| D3DPTFILTERCAPS_LINEARMIPLINEAR
| D3DPTFILTERCAPS_LINEARMIPNEAREST
|
3933 D3DPTFILTERCAPS_MIPLINEAR
| D3DPTFILTERCAPS_MIPNEAREST
| D3DPTFILTERCAPS_NEAREST
| D3DPTFILTERCAPS_MAGFLINEAR
|
3934 D3DPTFILTERCAPS_MAGFPOINT
| D3DPTFILTERCAPS_MINFLINEAR
| D3DPTFILTERCAPS_MINFPOINT
| D3DPTFILTERCAPS_MIPFLINEAR
|
3935 D3DPTFILTERCAPS_MIPFPOINT
;
3936 pc
->dwTextureBlendCaps
= D3DPTBLENDCAPS_ADD
| D3DPTBLENDCAPS_COPY
| D3DPTBLENDCAPS_DECAL
| D3DPTBLENDCAPS_DECALALPHA
| D3DPTBLENDCAPS_DECALMASK
|
3937 D3DPTBLENDCAPS_MODULATE
| D3DPTBLENDCAPS_MODULATEALPHA
| D3DPTBLENDCAPS_MODULATEMASK
;
3938 pc
->dwTextureAddressCaps
= D3DPTADDRESSCAPS_BORDER
| D3DPTADDRESSCAPS_CLAMP
| D3DPTADDRESSCAPS_WRAP
| D3DPTADDRESSCAPS_INDEPENDENTUV
;
3939 if (GL_extensions
.mirrored_repeat
== TRUE
) {
3940 pc
->dwTextureAddressCaps
|= D3DPTADDRESSCAPS_MIRROR
;
3942 pc
->dwStippleWidth
= 32;
3943 pc
->dwStippleHeight
= 32;
3946 static void fill_caps(void)
3948 GLint max_clip_planes
;
3951 /* Fill first all the fields with default values which will be overriden later on with
3952 correct ones from the GL code
3954 opengl_device_caps
.dwDevCaps
= D3DDEVCAPS_CANRENDERAFTERFLIP
| D3DDEVCAPS_DRAWPRIMTLVERTEX
| D3DDEVCAPS_EXECUTESYSTEMMEMORY
|
3955 D3DDEVCAPS_EXECUTEVIDEOMEMORY
| D3DDEVCAPS_FLOATTLVERTEX
| D3DDEVCAPS_TEXTURENONLOCALVIDMEM
| D3DDEVCAPS_TEXTURESYSTEMMEMORY
|
3956 D3DDEVCAPS_TEXTUREVIDEOMEMORY
| D3DDEVCAPS_TLVERTEXSYSTEMMEMORY
| D3DDEVCAPS_TLVERTEXVIDEOMEMORY
|
3957 /* D3D 7 capabilities */
3958 D3DDEVCAPS_DRAWPRIMITIVES2
| D3DDEVCAPS_HWTRANSFORMANDLIGHT
| D3DDEVCAPS_HWRASTERIZATION
;
3959 fill_opengl_primcaps(&(opengl_device_caps
.dpcLineCaps
));
3960 fill_opengl_primcaps(&(opengl_device_caps
.dpcTriCaps
));
3961 opengl_device_caps
.dwDeviceRenderBitDepth
= DDBD_16
|DDBD_24
|DDBD_32
;
3962 opengl_device_caps
.dwMinTextureWidth
= 1;
3963 opengl_device_caps
.dwMinTextureHeight
= 1;
3964 opengl_device_caps
.dwMaxTextureWidth
= 1024;
3965 opengl_device_caps
.dwMaxTextureHeight
= 1024;
3966 opengl_device_caps
.dwMaxTextureRepeat
= 16;
3967 opengl_device_caps
.dwMaxTextureAspectRatio
= 1024;
3968 opengl_device_caps
.dwMaxAnisotropy
= 0;
3969 opengl_device_caps
.dvGuardBandLeft
= 0.0;
3970 opengl_device_caps
.dvGuardBandRight
= 0.0;
3971 opengl_device_caps
.dvGuardBandTop
= 0.0;
3972 opengl_device_caps
.dvGuardBandBottom
= 0.0;
3973 opengl_device_caps
.dvExtentsAdjust
= 0.0;
3974 opengl_device_caps
.dwStencilCaps
= D3DSTENCILCAPS_DECRSAT
| D3DSTENCILCAPS_INCRSAT
| D3DSTENCILCAPS_INVERT
| D3DSTENCILCAPS_KEEP
|
3975 D3DSTENCILCAPS_REPLACE
| D3DSTENCILCAPS_ZERO
;
3976 opengl_device_caps
.dwTextureOpCaps
= D3DTEXOPCAPS_DISABLE
| D3DTEXOPCAPS_SELECTARG1
| D3DTEXOPCAPS_SELECTARG2
| D3DTEXOPCAPS_MODULATE4X
|
3977 D3DTEXOPCAPS_MODULATE2X
| D3DTEXOPCAPS_MODULATE
| D3DTEXOPCAPS_ADD
| D3DTEXOPCAPS_ADDSIGNED2X
| D3DTEXOPCAPS_ADDSIGNED
|
3978 D3DTEXOPCAPS_BLENDDIFFUSEALPHA
| D3DTEXOPCAPS_BLENDTEXTUREALPHA
| D3DTEXOPCAPS_BLENDFACTORALPHA
| D3DTEXOPCAPS_BLENDCURRENTALPHA
;
3979 if (GL_extensions
.max_texture_units
!= 0) {
3980 opengl_device_caps
.wMaxTextureBlendStages
= GL_extensions
.max_texture_units
;
3981 opengl_device_caps
.wMaxSimultaneousTextures
= GL_extensions
.max_texture_units
;
3982 opengl_device_caps
.dwFVFCaps
= D3DFVFCAPS_DONOTSTRIPELEMENTS
| GL_extensions
.max_texture_units
;
3984 opengl_device_caps
.wMaxTextureBlendStages
= 1;
3985 opengl_device_caps
.wMaxSimultaneousTextures
= 1;
3986 opengl_device_caps
.dwFVFCaps
= D3DFVFCAPS_DONOTSTRIPELEMENTS
| 1;
3988 opengl_device_caps
.dwMaxActiveLights
= 16;
3989 opengl_device_caps
.dvMaxVertexW
= 100000000.0; /* No idea exactly what to put here... */
3990 opengl_device_caps
.deviceGUID
= IID_IDirect3DTnLHalDevice
;
3991 opengl_device_caps
.wMaxUserClipPlanes
= 1;
3992 opengl_device_caps
.wMaxVertexBlendMatrices
= 0;
3993 opengl_device_caps
.dwVertexProcessingCaps
= D3DVTXPCAPS_TEXGEN
| D3DVTXPCAPS_MATERIALSOURCE7
| D3DVTXPCAPS_VERTEXFOG
|
3994 D3DVTXPCAPS_DIRECTIONALLIGHTS
| D3DVTXPCAPS_POSITIONALLIGHTS
| D3DVTXPCAPS_LOCALVIEWER
;
3995 opengl_device_caps
.dwReserved1
= 0;
3996 opengl_device_caps
.dwReserved2
= 0;
3997 opengl_device_caps
.dwReserved3
= 0;
3998 opengl_device_caps
.dwReserved4
= 0;
4000 /* And now some GL overides :-) */
4001 glGetIntegerv(GL_MAX_TEXTURE_SIZE
, (GLint
*) &opengl_device_caps
.dwMaxTextureWidth
);
4002 opengl_device_caps
.dwMaxTextureHeight
= opengl_device_caps
.dwMaxTextureWidth
;
4003 opengl_device_caps
.dwMaxTextureAspectRatio
= opengl_device_caps
.dwMaxTextureWidth
;
4004 TRACE(": max texture size = %ld\n", opengl_device_caps
.dwMaxTextureWidth
);
4006 glGetIntegerv(GL_MAX_LIGHTS
, (GLint
*) &opengl_device_caps
.dwMaxActiveLights
);
4007 TRACE(": max active lights = %ld\n", opengl_device_caps
.dwMaxActiveLights
);
4009 glGetIntegerv(GL_MAX_CLIP_PLANES
, &max_clip_planes
);
4010 opengl_device_caps
.wMaxUserClipPlanes
= max_clip_planes
;
4011 TRACE(": max clipping planes = %d\n", opengl_device_caps
.wMaxUserClipPlanes
);
4013 glGetIntegerv(GL_DEPTH_BITS
, &depth_bits
);
4014 TRACE(": Z bits = %d\n", depth_bits
);
4015 switch (depth_bits
) {
4016 case 16: opengl_device_caps
.dwDeviceZBufferBitDepth
= DDBD_16
; break;
4017 case 24: opengl_device_caps
.dwDeviceZBufferBitDepth
= DDBD_16
|DDBD_24
; break;
4019 default: opengl_device_caps
.dwDeviceZBufferBitDepth
= DDBD_16
|DDBD_24
|DDBD_32
; break;
4024 d3ddevice_init_at_startup(void *gl_handle
)
4026 XVisualInfo
template;
4031 Drawable drawable
= (Drawable
) GetPropA(GetDesktopWindow(), "__wine_x11_whole_window");
4032 XWindowAttributes win_attr
;
4033 GLXContext gl_context
;
4035 const char *glExtensions
;
4036 const char *glVersion
;
4037 const char *glXExtensions
= NULL
;
4038 const void *(*pglXGetProcAddressARB
)(const GLubyte
*) = NULL
;
4039 int major
, minor
, patch
;
4041 TRACE("Initializing GL...\n");
4043 /* Get a default rendering context to have the 'caps' function query some info from GL */
4044 device_context
= GetDC(0);
4045 display
= get_display(device_context
);
4046 ReleaseDC(0, device_context
);
4049 if (XGetWindowAttributes(display
, drawable
, &win_attr
)) {
4050 visual
= win_attr
.visual
;
4052 visual
= DefaultVisual(display
, DefaultScreen(display
));
4054 template.visualid
= XVisualIDFromVisual(visual
);
4055 vis
= XGetVisualInfo(display
, VisualIDMask
, &template, &num
);
4058 WARN("Error creating visual info for capabilities initialization - D3D support disabled !\n");
4061 gl_context
= glXCreateContext(display
, vis
, NULL
, GL_TRUE
);
4063 if (gl_context
== NULL
) {
4065 WARN("Error creating default context for capabilities initialization - D3D support disabled !\n");
4068 if (glXMakeCurrent(display
, drawable
, gl_context
) == False
) {
4069 glXDestroyContext(display
, gl_context
);
4071 WARN("Error setting default context as current for capabilities initialization - D3D support disabled !\n");
4075 /* Then, query all extensions */
4076 glXExtensions
= glXQueryExtensionsString(display
, DefaultScreen(display
));
4077 glExtensions
= (const char *) glGetString(GL_EXTENSIONS
);
4078 glVersion
= (const char *) glGetString(GL_VERSION
);
4079 if ((glXExtensions
!= NULL
) && (gl_handle
!= NULL
) && (strstr(glXExtensions
, "GLX_ARB_get_proc_address"))) {
4080 pglXGetProcAddressARB
= wine_dlsym(gl_handle
, "glXGetProcAddressARB", NULL
, 0);
4083 /* Parse the GL version string */
4084 sscanf(glVersion
, "%d.%d.%d", &major
, &minor
, &patch
);
4085 TRACE("GL version %d.%d.%d\n", major
, minor
, patch
);
4087 /* And starts to fill the extension context properly */
4088 memset(&GL_extensions
, 0, sizeof(GL_extensions
));
4089 TRACE("GL supports following extensions used by Wine :\n");
4091 /* Mirrored Repeat extension :
4092 - GL_ARB_texture_mirrored_repeat
4093 - GL_IBM_texture_mirrored_repeat
4096 if ((strstr(glExtensions
, "GL_ARB_texture_mirrored_repeat")) ||
4097 (strstr(glExtensions
, "GL_IBM_texture_mirrored_repeat")) ||
4099 ((major
== 1) && (minor
>= 4))) {
4100 TRACE(" - mirrored repeat\n");
4101 GL_extensions
.mirrored_repeat
= TRUE
;
4104 /* Texture LOD Bias :
4105 - GL_EXT_texture_lod_bias
4107 if (strstr(glExtensions
, "GL_EXT_texture_lod_bias")) {
4108 TRACE(" - texture lod bias\n");
4109 GL_extensions
.mipmap_lodbias
= TRUE
;
4112 /* For all subsequent extensions, we need glXGetProcAddress */
4113 if (pglXGetProcAddressARB
!= NULL
) {
4114 /* Multi-texturing :
4115 - GL_ARB_multitexture
4118 if ((strstr(glExtensions
, "GL_ARB_multitexture")) ||
4120 ((major
== 1) && (minor
> 2)) ||
4121 ((major
== 1) && (minor
== 2) && (patch
>= 1))) {
4122 glGetIntegerv(GL_MAX_TEXTURE_UNITS_WINE
, &(GL_extensions
.max_texture_units
));
4123 TRACE(" - multi-texturing (%d stages)\n", GL_extensions
.max_texture_units
);
4124 /* We query the ARB version to be the most portable we can... */
4125 GL_extensions
.glActiveTexture
= pglXGetProcAddressARB("glActiveTextureARB");
4126 GL_extensions
.glMultiTexCoord2fv
= pglXGetProcAddressARB("glMultiTexCoord2fv");
4130 /* Fill the D3D capabilities according to what GL tells us... */
4133 /* And frees this now-useless context */
4134 glXMakeCurrent(display
, None
, NULL
);
4135 glXDestroyContext(display
, gl_context
);