Commit fc58c2a9 authored by Lionel Ulmer's avatar Lionel Ulmer Committed by Alexandre Julliard

- some GL critical section fixes

- only bind textures at start of rendering - optimized the texture parameter code - optimize of the 'dirty checking code' for mipmapping - handles the MAXMIPLEVEL texture parameter
parent 4aba282b
......@@ -56,13 +56,6 @@ const GUID IID_D3DDEVICE_OpenGL = {
{ 0x82,0x2d,0xa8,0xd5,0x31,0x87,0xca,0xfa }
};
#ifndef HAVE_GLEXT_PROTOTYPES
/* This is for non-OpenGL ABI compliant glext.h headers :-) */
typedef void (* PFNGLCOLORTABLEEXTPROC) (GLenum target, GLenum internalFormat,
GLsizei width, GLenum format, GLenum type,
const GLvoid *table);
#endif
const float id_mat[16] = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
......@@ -79,6 +72,8 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This,
DWORD dwIndexCount,
DWORD dwFlags) ;
static DWORD draw_primitive_handle_textures(IDirect3DDeviceImpl *This);
/* retrieve the X display to use on a given DC */
inline static Display *get_display( HDC hdc )
{
......@@ -651,9 +646,7 @@ GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
IDirect3DMaterialImpl *mat = (IDirect3DMaterialImpl *) dwLightState;
if (mat != NULL) {
ENTER_GL();
mat->activate(mat);
LEAVE_GL();
} else {
ERR(" D3DLIGHTSTATE_MATERIAL called with NULL material !!!\n");
}
......@@ -1111,9 +1104,6 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This,
glThis->state = SURFACE_GL;
/* Compute the number of active texture stages */
while (This->current_texture[num_active_stages] != NULL) num_active_stages++;
if (TRACE_ON(ddraw)) {
TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
}
......@@ -1125,6 +1115,9 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This,
if ((d3dvtVertexType & D3DFVF_NORMAL) == 0) glNormal3f(0.0, 0.0, 0.0);
}
/* Compute the number of active texture stages and set the various texture parameters */
num_active_stages = draw_primitive_handle_textures(This);
draw_primitive_handle_GL_state(This,
(d3dvtVertexType & D3DFVF_POSITION_MASK) != D3DFVF_XYZ,
vertex_lighted);
......@@ -1460,70 +1453,6 @@ GL_IDirect3DDeviceImpl_7_3T_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface,
return DD_OK;
}
static GLenum
convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
{
GLenum gl_state;
if (dwMipState == D3DTFP_NONE) {
switch (dwMinState) {
case D3DTFN_POINT: gl_state = GL_NEAREST; break;
case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
default: gl_state = GL_LINEAR; break;
}
} else if (dwMipState == D3DTFP_POINT) {
switch (dwMinState) {
case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
}
} else {
switch (dwMinState) {
case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
}
}
return gl_state;
}
static GLenum
convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
{
GLenum gl_state;
switch (dwState) {
case D3DTFG_POINT:
gl_state = GL_NEAREST;
break;
case D3DTFG_LINEAR:
gl_state = GL_LINEAR;
break;
default:
gl_state = GL_LINEAR;
break;
}
return gl_state;
}
static GLenum
convert_tex_address_to_GL(D3DTEXTUREADDRESS dwState)
{
GLenum gl_state;
switch (dwState) {
case D3DTADDRESS_WRAP: gl_state = GL_REPEAT; break;
case D3DTADDRESS_CLAMP: gl_state = GL_CLAMP; break;
case D3DTADDRESS_BORDER: gl_state = GL_CLAMP_TO_EDGE; break;
#if defined(GL_VERSION_1_4)
case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT; break;
#elif defined(GL_ARB_texture_mirrored_repeat)
case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT_ARB; break;
#endif
default: gl_state = GL_REPEAT; break;
}
return gl_state;
}
/* We need a static function for that to handle the 'special' case of 'SELECT_ARG2' */
static BOOLEAN
handle_color_alpha_args(IDirect3DDeviceImpl *This, DWORD dwStage, D3DTEXTURESTAGESTATETYPE d3dTexStageStateType, DWORD dwState, D3DTEXTUREOP tex_op)
......@@ -1677,10 +1606,6 @@ GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
}
}
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
break;
case D3DTSS_MAGFILTER:
......@@ -1691,14 +1616,11 @@ GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
default: FIXME(" Unhandled stage type : D3DTSS_MAGFILTER => %08lx\n", dwState); break;
}
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, convert_mag_filter_to_GL(dwState));
break;
case D3DTSS_ADDRESS:
case D3DTSS_ADDRESSU:
case D3DTSS_ADDRESSV: {
GLenum arg = convert_tex_address_to_GL(dwState);
switch ((D3DTEXTUREADDRESS) dwState) {
case D3DTADDRESS_WRAP: TRACE(" Stage type is : %s => D3DTADDRESS_WRAP\n", type); break;
case D3DTADDRESS_CLAMP: TRACE(" Stage type is : %s => D3DTADDRESS_CLAMP\n", type); break;
......@@ -1710,13 +1632,6 @@ GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
#endif
default: FIXME(" Unhandled stage type : %s => %08lx\n", type, dwState); break;
}
if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
(d3dTexStageStateType == D3DTSS_ADDRESSU))
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, arg);
if ((d3dTexStageStateType == D3DTSS_ADDRESS) ||
(d3dTexStageStateType == D3DTSS_ADDRESSV))
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, arg);
} break;
case D3DTSS_ALPHAOP:
......@@ -1917,29 +1832,16 @@ GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
} break;
case D3DTSS_MAXMIPLEVEL:
if (dwState == 0) {
TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
} else {
FIXME(" Unhandled stage type : D3DTSS_MAXMIPLEVEL => %ld\n", dwState);
}
TRACE(" Stage type : D3DTSS_MAXMIPLEVEL => 0 (disabled) \n");
break;
case D3DTSS_BORDERCOLOR: {
GLfloat color[4];
color[0] = ((dwState >> 16) & 0xFF) / 255.0;
color[1] = ((dwState >> 8) & 0xFF) / 255.0;
color[2] = ((dwState >> 0) & 0xFF) / 255.0;
color[3] = ((dwState >> 24) & 0xFF) / 255.0;
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
case D3DTSS_BORDERCOLOR:
TRACE(" Stage type : D3DTSS_BORDERCOLOR => %02lx %02lx %02lx %02lx (RGBA)\n",
((dwState >> 16) & 0xFF),
((dwState >> 8) & 0xFF),
((dwState >> 0) & 0xFF),
((dwState >> 24) & 0xFF));
} break;
break;
case D3DTSS_TEXCOORDINDEX: {
BOOLEAN handled = TRUE;
......@@ -2003,6 +1905,48 @@ GL_IDirect3DDeviceImpl_7_3T_SetTextureStageState(LPDIRECT3DDEVICE7 iface,
return DD_OK;
}
static DWORD
draw_primitive_handle_textures(IDirect3DDeviceImpl *This)
{
IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
DWORD stage;
for (stage = 0; stage < MAX_TEXTURES; stage++) {
IDirectDrawSurfaceImpl *surf_ptr = This->current_texture[stage];
/* First check if we need to bind any other texture for this stage */
if (This->current_texture[stage] != glThis->current_bound_texture[stage]) {
if (This->current_texture[stage] == NULL) {
TRACE(" disabling 2D texturing for stage %ld.\n", stage);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
} else {
GLenum tex_name = ((IDirect3DTextureGLImpl *) surf_ptr->tex_private)->tex_name;
if (glThis->current_bound_texture[stage] == NULL) {
if (This->state_block.texture_stage_state[stage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
glEnable(GL_TEXTURE_2D);
}
}
TRACE(" activating OpenGL texture id %d for stage %ld.\n", tex_name, stage);
glBindTexture(GL_TEXTURE_2D, tex_name);
}
glThis->current_bound_texture[stage] = This->current_texture[stage];
}
/* If no texure valid for this stage, go out of the loop */
if (This->current_texture[stage] == NULL) break;
/* Then check if we need to flush this texture to GL or not (ie did it change) ?.
This will also update the various texture parameters if needed.
*/
gltex_upload_texture(surf_ptr, This, stage);
}
return stage;
}
HRESULT WINAPI
GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
DWORD dwStage,
......@@ -2018,57 +1962,13 @@ GL_IDirect3DDeviceImpl_7_3T_SetTexture(LPDIRECT3DDEVICE7 iface,
IDirectDrawSurface7_Release(ICOM_INTERFACE(This->current_texture[dwStage], IDirectDrawSurface7));
}
ENTER_GL();
if (lpTexture2 == NULL) {
This->current_texture[dwStage] = NULL;
TRACE(" disabling 2D texturing.\n");
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
} else {
IDirectDrawSurfaceImpl *tex_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpTexture2);
GLint max_mip_level;
GLfloat color[4];
IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7)); /* Not sure about this either */
if (This->current_texture[dwStage] == tex_impl) {
/* No need to do anything as the texture did not change. */
return DD_OK;
}
IDirectDrawSurface7_AddRef(ICOM_INTERFACE(tex_impl, IDirectDrawSurface7));
This->current_texture[dwStage] = tex_impl;
if (This->state_block.texture_stage_state[dwStage][D3DTSS_COLOROP - 1] != D3DTOP_DISABLE) {
/* Do not re-enable texturing if it was disabled due to the COLOROP code */
glEnable(GL_TEXTURE_2D);
TRACE(" enabling 2D texturing.\n");
}
gltex_upload_texture(tex_impl);
if ((tex_impl->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
max_mip_level = 0;
} else {
max_mip_level = tex_impl->surface_desc.u2.dwMipMapCount - 1;
}
/* Now we need to reset all glTexParameter calls for this particular texture... */
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
convert_mag_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MAGFILTER - 1]));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
convert_min_filter_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_MINFILTER - 1],
This->state_block.texture_stage_state[dwStage][D3DTSS_MIPFILTER - 1]));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
convert_tex_address_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSU - 1]));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
convert_tex_address_to_GL(This->state_block.texture_stage_state[dwStage][D3DTSS_ADDRESSV - 1]));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
color[0] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 16) & 0xFF) / 255.0;
color[1] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 8) & 0xFF) / 255.0;
color[2] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 0) & 0xFF) / 255.0;
color[3] = ((This->state_block.texture_stage_state[dwStage][D3DTSS_BORDERCOLOR - 1] >> 24) & 0xFF) / 255.0;
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
}
LEAVE_GL();
return DD_OK;
}
......@@ -2101,6 +2001,7 @@ GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
This->current_material = *lpMat;
ENTER_GL();
glMaterialfv(GL_FRONT_AND_BACK,
GL_DIFFUSE,
(float *) &(This->current_material.u.diffuse));
......@@ -2116,6 +2017,7 @@ GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
glMaterialf(GL_FRONT_AND_BACK,
GL_SHININESS,
This->current_material.u4.power); /* Not sure about this... */
LEAVE_GL();
return DD_OK;
}
......@@ -2173,6 +2075,7 @@ GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
if (dwLightIndex >= MAX_LIGHTS) return DDERR_INVALIDPARAMS;
ENTER_GL();
if (bEnable) {
if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
/* Set the default parameters.. */
......@@ -2191,6 +2094,7 @@ GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
glDisable(GL_LIGHT0 + dwLightIndex);
This->active_lights &= ~(0x00000001 << dwLightIndex);
}
LEAVE_GL();
return DD_OK;
}
......@@ -2608,7 +2512,8 @@ d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
trans_mat[ 1] = 0.0; trans_mat[ 5] = -2.0 / height; trans_mat[ 9] = 0.0; trans_mat[13] = 1.0;
trans_mat[ 2] = 0.0; trans_mat[ 6] = 0.0; trans_mat[10] = 1.0; trans_mat[14] = -1.0;
trans_mat[ 3] = 0.0; trans_mat[ 7] = 0.0; trans_mat[11] = 0.0; trans_mat[15] = 1.0;
ENTER_GL();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/* See the OpenGL Red Book for an explanation of the following translation (in the OpenGL
......@@ -2622,12 +2527,14 @@ d3ddevice_set_ortho(IDirect3DDeviceImpl *This)
glTranslatef(0.375, 0.375, 0);
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(trans_mat);
LEAVE_GL();
}
void
d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
D3DMATRIX *world_mat, D3DMATRIX *view_mat, D3DMATRIX *proj_mat)
{
ENTER_GL();
if ((matrices & (VIEWMAT_CHANGED|WORLDMAT_CHANGED)) != 0) {
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf((float *) view_mat);
......@@ -2730,6 +2637,7 @@ d3ddevice_set_matrices(IDirect3DDeviceImpl *This, DWORD matrices,
glMatrixMode(GL_PROJECTION);
glLoadMatrixf((float *) proj_mat);
}
LEAVE_GL();
}
void
......@@ -2898,8 +2806,6 @@ static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCREC
RECT loc_rect;
IDirect3DDeviceGLImpl* gl_d3d_dev = (IDirect3DDeviceGLImpl*) d3d_dev;
GLint depth_test, alpha_test, cull_face, lighting, tex_env, blend, stencil_test, fog;
GLuint initial_texture;
GLint tex_state;
int x, y;
BOOLEAN initial = FALSE;
......@@ -2913,7 +2819,9 @@ static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCREC
TRACE(" flushing memory back to the frame-buffer (%ld,%ld) x (%ld,%ld).\n", loc_rect.top, loc_rect.left, loc_rect.right, loc_rect.bottom);
glGetIntegerv(GL_TEXTURE_BINDING_2D, &initial_texture);
/* This is a hack to prevent querying the current texture from GL */
gl_d3d_dev->current_bound_texture[0] = (IDirectDrawSurfaceImpl *) 0x00000001;
if (gl_d3d_dev->unlock_tex == 0) {
glGenTextures(1, &gl_d3d_dev->unlock_tex);
glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
......@@ -2923,11 +2831,11 @@ static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCREC
} else {
glBindTexture(GL_TEXTURE_2D, gl_d3d_dev->unlock_tex);
}
if (upload_surface_to_tex_memory_init(surf, 0, &gl_d3d_dev->current_internal_format,
initial, FALSE, UNLOCK_TEX_SIZE, UNLOCK_TEX_SIZE) != D3D_OK) {
ERR(" unsupported pixel format at frame buffer flush.\n");
glBindTexture(GL_TEXTURE_2D, initial_texture);
return;
}
......@@ -2937,7 +2845,6 @@ static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCREC
glGetIntegerv(GL_CULL_FACE, &cull_face);
glGetIntegerv(GL_LIGHTING, &lighting);
glGetIntegerv(GL_BLEND, &blend);
glGetIntegerv(GL_TEXTURE_2D, &tex_state);
glGetIntegerv(GL_FOG, &fog);
glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env);
glMatrixMode(GL_TEXTURE);
......@@ -2998,8 +2905,6 @@ static void d3ddevice_flush_to_frame_buffer(IDirect3DDeviceImpl *d3d_dev, LPCREC
if (cull_face != 0) glEnable(GL_CULL_FACE);
if (blend != 0) glEnable(GL_BLEND);
if (fog != 0) glEnable(GL_FOG);
glBindTexture(GL_TEXTURE_2D, initial_texture);
if (tex_state == 0) glDisable(GL_TEXTURE_2D);
glDisable(GL_SCISSOR_TEST);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_SWAP_BYTES, FALSE);
......
......@@ -89,23 +89,169 @@ gltex_download_texture(IDirectDrawSurfaceImpl *surf_ptr) {
FIXME("This is not supported yet... Expect some graphical glitches !!!\n");
/* GL and memory are in sync again ... */
/* GL and memory are in sync again ...
No need to change the 'global' flag as it only handles the 'MEMORY_DIRTY' case.
*/
gl_surf_ptr->dirty_flag = SURFACE_MEMORY;
return DD_OK;
}
static GLenum
convert_min_filter_to_GL(D3DTEXTUREMINFILTER dwMinState, D3DTEXTUREMIPFILTER dwMipState)
{
GLenum gl_state;
if (dwMipState == D3DTFP_NONE) {
switch (dwMinState) {
case D3DTFN_POINT: gl_state = GL_NEAREST; break;
case D3DTFN_LINEAR: gl_state = GL_LINEAR; break;
default: gl_state = GL_LINEAR; break;
}
} else if (dwMipState == D3DTFP_POINT) {
switch (dwMinState) {
case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_NEAREST; break;
case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
default: gl_state = GL_LINEAR_MIPMAP_NEAREST; break;
}
} else {
switch (dwMinState) {
case D3DTFN_POINT: gl_state = GL_NEAREST_MIPMAP_LINEAR; break;
case D3DTFN_LINEAR: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
default: gl_state = GL_LINEAR_MIPMAP_LINEAR; break;
}
}
return gl_state;
}
static GLenum
convert_mag_filter_to_GL(D3DTEXTUREMAGFILTER dwState)
{
GLenum gl_state;
switch (dwState) {
case D3DTFG_POINT:
gl_state = GL_NEAREST;
break;
case D3DTFG_LINEAR:
gl_state = GL_LINEAR;
break;
default:
gl_state = GL_LINEAR;
break;
}
return gl_state;
}
static GLenum
convert_tex_address_to_GL(D3DTEXTUREADDRESS dwState)
{
GLenum gl_state;
switch (dwState) {
case D3DTADDRESS_WRAP: gl_state = GL_REPEAT; break;
case D3DTADDRESS_CLAMP: gl_state = GL_CLAMP; break;
case D3DTADDRESS_BORDER: gl_state = GL_CLAMP_TO_EDGE; break;
#if defined(GL_VERSION_1_4)
case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT; break;
#elif defined(GL_ARB_texture_mirrored_repeat)
case D3DTADDRESS_MIRROR: gl_state = GL_MIRRORED_REPEAT_ARB; break;
#endif
default: gl_state = GL_REPEAT; break;
}
return gl_state;
}
HRESULT
gltex_upload_texture(IDirectDrawSurfaceImpl *surf_ptr) {
gltex_upload_texture(IDirectDrawSurfaceImpl *surf_ptr, IDirect3DDeviceImpl *d3ddev, DWORD stage) {
IDirect3DTextureGLImpl *gl_surf_ptr = (IDirect3DTextureGLImpl *) surf_ptr->tex_private;
GLuint tex_name = gl_surf_ptr->tex_name;
BOOLEAN changed = FALSE;
TRACE(" activating OpenGL texture id %d.\n", tex_name);
glBindTexture(GL_TEXTURE_2D, tex_name);
if (surf_ptr->mipmap_level != 0) {
WARN(" application activating a sub-level of the mipmapping chain (level %d) !\n", surf_ptr->mipmap_level);
}
/* Now check if the texture parameters for this texture are still in-line with what D3D expect
us to do..
NOTE: there is no check for the situation where the same texture is bound to multiple stage
but with different parameters per stage.
*/
if ((gl_surf_ptr->tex_parameters == NULL) ||
(gl_surf_ptr->tex_parameters[D3DTSS_MAXMIPLEVEL - D3DTSS_ADDRESSU] !=
d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1])) {
DWORD max_mip_level;
if ((surf_ptr->surface_desc.ddsCaps.dwCaps & DDSCAPS_MIPMAP) == 0) {
max_mip_level = 0;
} else {
max_mip_level = surf_ptr->surface_desc.u2.dwMipMapCount - 1;
if (d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1] != 0) {
if (max_mip_level >= d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1]) {
max_mip_level = d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAXMIPLEVEL - 1] - 1;
}
}
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, max_mip_level);
changed = TRUE;
}
if ((gl_surf_ptr->tex_parameters == NULL) ||
(gl_surf_ptr->tex_parameters[D3DTSS_MAGFILTER - D3DTSS_ADDRESSU] !=
d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAGFILTER - 1])) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
convert_mag_filter_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_MAGFILTER - 1]));
changed = TRUE;
}
if ((gl_surf_ptr->tex_parameters == NULL) ||
(gl_surf_ptr->tex_parameters[D3DTSS_MINFILTER - D3DTSS_ADDRESSU] !=
d3ddev->state_block.texture_stage_state[stage][D3DTSS_MINFILTER - 1]) ||
(gl_surf_ptr->tex_parameters[D3DTSS_MIPFILTER - D3DTSS_ADDRESSU] !=
d3ddev->state_block.texture_stage_state[stage][D3DTSS_MIPFILTER - 1])) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
convert_min_filter_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_MINFILTER - 1],
d3ddev->state_block.texture_stage_state[stage][D3DTSS_MIPFILTER - 1]));
changed = TRUE;
}
if ((gl_surf_ptr->tex_parameters == NULL) ||
(gl_surf_ptr->tex_parameters[D3DTSS_ADDRESSU - D3DTSS_ADDRESSU] !=
d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSU - 1])) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
convert_tex_address_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSU - 1]));
changed = TRUE;
}
if ((gl_surf_ptr->tex_parameters == NULL) ||
(gl_surf_ptr->tex_parameters[D3DTSS_ADDRESSV - D3DTSS_ADDRESSU] !=
d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSV - 1])) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
convert_tex_address_to_GL(d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSV - 1]));
changed = TRUE;
}
if ((gl_surf_ptr->tex_parameters == NULL) ||
(gl_surf_ptr->tex_parameters[D3DTSS_BORDERCOLOR - D3DTSS_ADDRESSU] !=
d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1])) {
GLfloat color[4];
color[0] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >> 16) & 0xFF) / 255.0;
color[1] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >> 8) & 0xFF) / 255.0;
color[2] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >> 0) & 0xFF) / 255.0;
color[3] = ((d3ddev->state_block.texture_stage_state[stage][D3DTSS_BORDERCOLOR - 1] >> 24) & 0xFF) / 255.0;
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, color);
changed = TRUE;
}
if (changed == TRUE) {
if (gl_surf_ptr->tex_parameters == NULL) {
gl_surf_ptr->tex_parameters = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(DWORD) * (D3DTSS_MAXMIPLEVEL + 1 - D3DTSS_ADDRESSU));
}
memcpy(gl_surf_ptr->tex_parameters, &(d3ddev->state_block.texture_stage_state[stage][D3DTSS_ADDRESSU - 1]),
sizeof(DWORD) * (D3DTSS_MAXMIPLEVEL + 1 - D3DTSS_ADDRESSU));
}
if (*(gl_surf_ptr->global_dirty_flag) != SURFACE_MEMORY_DIRTY) {
TRACE(" nothing to do - memory copy and GL state in synch for all texture levels.\n");
return DD_OK;
}
while (surf_ptr != NULL) {
IDirect3DTextureGLImpl *gl_surf_ptr = (IDirect3DTextureGLImpl *) surf_ptr->tex_private;
......@@ -133,7 +279,9 @@ gltex_upload_texture(IDirectDrawSurfaceImpl *surf_ptr) {
surf_ptr = NULL;
}
}
*(gl_surf_ptr->global_dirty_flag) = SURFACE_MEMORY;
return DD_OK;
}
......@@ -164,6 +312,7 @@ gltex_setcolorkey_cb(IDirectDrawSurfaceImpl *This, DWORD dwFlags, LPDDCOLORKEY c
}
glThis->dirty_flag = SURFACE_MEMORY_DIRTY;
*(glThis->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
/* TODO: check color-keying on mipmapped surfaces... */
return DD_OK;
......@@ -277,6 +426,7 @@ gltex_bltfast(IDirectDrawSurfaceImpl *surf_ptr, DWORD dstx,
glBindTexture(GL_TEXTURE_2D, cur_tex);
LEAVE_GL();
/* The SURFACE_GL case is not handled by the 'global' dirty flag */
gl_surf_ptr->dirty_flag = SURFACE_GL;
return DD_OK;
......@@ -353,6 +503,7 @@ static void gltex_set_palette(IDirectDrawSurfaceImpl* This, IDirectDrawPaletteIm
/* And set the dirty flag */
glThis->dirty_flag = SURFACE_MEMORY_DIRTY;
*(glThis->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
/* TODO: check palette on mipmapped surfaces...
TODO: do we need to re-upload in case of usage of the paletted texture extension ? */
......@@ -408,8 +559,10 @@ gltex_unlock_update(IDirectDrawSurfaceImpl* This, LPCRECT pRect)
glThis->unlock_update(This, pRect);
/* Set the dirty flag according to the lock type */
if ((This->lastlocktype & DDLOCK_READONLY) == 0)
if ((This->lastlocktype & DDLOCK_READONLY) == 0) {
glThis->dirty_flag = SURFACE_MEMORY_DIRTY;
*(glThis->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
}
}
HRESULT WINAPI
......@@ -499,6 +652,7 @@ GL_IDirect3DTextureImpl_2_1T_Load(LPDIRECT3DTEXTURE2 iface,
/* Set this texture as dirty */
gl_dst_ptr->dirty_flag = SURFACE_MEMORY_DIRTY;
*(gl_dst_ptr->global_dirty_flag) = SURFACE_MEMORY_DIRTY;
}
}
......@@ -682,16 +836,19 @@ HRESULT d3dtexture_create(IDirectDrawImpl *d3d, IDirectDrawSurfaceImpl *surf, BO
to save those... */
surf->aux_blt = gltex_blt;
surf->aux_bltfast = gltex_bltfast;
ENTER_GL();
if (surf->mipmap_level == 0) {
glGenTextures(1, &(private->tex_name));
if (private->tex_name == 0) ERR("Error at creation of OpenGL texture ID !\n");
TRACE(" GL texture created for surface %p (private data at %p and GL id %d).\n", surf, private, private->tex_name);
private->__global_dirty_flag = (at_creation == FALSE ? SURFACE_MEMORY_DIRTY : SURFACE_MEMORY);
private->global_dirty_flag = &(private->__global_dirty_flag);
} else {
private->tex_name = ((IDirect3DTextureGLImpl *) (main->tex_private))->tex_name;
TRACE(" GL texture created for surface %p (private data at %p and GL id reusing id %d from surface %p (%p)).\n",
surf, private, private->tex_name, main, main->tex_private);
private->global_dirty_flag = &(((IDirect3DTextureGLImpl *) (main->tex_private))->__global_dirty_flag);
}
LEAVE_GL();
......
......@@ -68,6 +68,18 @@ typedef struct IDirect3DTextureGLImpl
BOOLEAN initial_upload_done;
SURFACE_STATE dirty_flag;
/* This is used to optimize dirty checking in case of mipmapping.
Note that a bitmap could have been used but it was not worth the pain as it will be very rare
to have only one mipmap level change...
The __global_dirty_flag will only be set for the main mipmap level.
*/
SURFACE_STATE __global_dirty_flag;
SURFACE_STATE *global_dirty_flag;
/* This is to optimize the 'per-texture' parameters. */
DWORD *tex_parameters;
/* Surface optimization */
void *surface_ptr;
......@@ -94,6 +106,9 @@ typedef struct IDirect3DDeviceGLImpl
GLXContext gl_context;
/* This stores the textures which are actually bound to the GL context */
IDirectDrawSurfaceImpl *current_bound_texture[MAX_TEXTURES];
/* The last type of vertex drawn */
GL_TRANSFORM_STATE transform_state;
......@@ -139,7 +154,7 @@ extern HRESULT d3ddevice_enumerate7(LPD3DENUMDEVICESCALLBACK7 cb, LPVOID context
extern HRESULT d3ddevice_find(IDirectDrawImpl *d3d, LPD3DFINDDEVICESEARCH lpD3DDFS, LPD3DFINDDEVICERESULT lplpD3DDevice);
/* Used to upload the texture */
extern HRESULT gltex_upload_texture(IDirectDrawSurfaceImpl *This) ;
extern HRESULT gltex_upload_texture(IDirectDrawSurfaceImpl *This, IDirect3DDeviceImpl *d3ddev, DWORD stage) ;
/* Used to set-up our orthographic projection */
extern void d3ddevice_set_ortho(IDirect3DDeviceImpl *This) ;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment