wined3d: Allow the depth buffer to be shared between onscreen and offscreen rendering modes.
This commit is contained in:
parent
6d66085150
commit
ef2c062c09
|
@ -7006,6 +7006,8 @@ static void set_depth_stencil_fbo(IWineD3DDevice *iface, IWineD3DSurface *depth_
|
||||||
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
|
IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
|
||||||
|
|
||||||
|
This->depth_copy_state = WINED3D_DCS_NO_COPY;
|
||||||
|
|
||||||
bind_fbo(iface);
|
bind_fbo(iface);
|
||||||
|
|
||||||
if (depth_stencil_impl) {
|
if (depth_stencil_impl) {
|
||||||
|
@ -7275,6 +7277,9 @@ static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
|
||||||
BOOL oldRecording;
|
BOOL oldRecording;
|
||||||
IWineD3DStateBlockImpl *oldUpdateStateBlock;
|
IWineD3DStateBlockImpl *oldUpdateStateBlock;
|
||||||
|
|
||||||
|
/* Nothing to update, return. */
|
||||||
|
if (This->render_offscreen == isTexture) return;
|
||||||
|
|
||||||
/* Disable recording */
|
/* Disable recording */
|
||||||
oldUpdateStateBlock = This->updateStateBlock;
|
oldUpdateStateBlock = This->updateStateBlock;
|
||||||
oldRecording= This->isRecordingState;
|
oldRecording= This->isRecordingState;
|
||||||
|
@ -7282,6 +7287,9 @@ static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
|
||||||
This->updateStateBlock = This->stateBlock;
|
This->updateStateBlock = This->stateBlock;
|
||||||
|
|
||||||
This->render_offscreen = isTexture;
|
This->render_offscreen = isTexture;
|
||||||
|
if (This->depth_copy_state != WINED3D_DCS_NO_COPY) {
|
||||||
|
This->depth_copy_state = WINED3D_DCS_COPY;
|
||||||
|
}
|
||||||
This->last_was_rhw = FALSE;
|
This->last_was_rhw = FALSE;
|
||||||
This->proj_valid = FALSE;
|
This->proj_valid = FALSE;
|
||||||
IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
|
IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* Copyright 2002-2004 Raphael Junqueira
|
* Copyright 2002-2004 Raphael Junqueira
|
||||||
* Copyright 2004 Christian Costa
|
* Copyright 2004 Christian Costa
|
||||||
* Copyright 2005 Oliver Stieber
|
* Copyright 2005 Oliver Stieber
|
||||||
|
* Copyright 2006 Henri Verbeet
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
@ -2088,6 +2089,196 @@ static void check_fbo_status(IWineD3DDevice *iface) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GLuint create_arb_blt_vertex_program(IWineD3DDevice *iface) {
|
||||||
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
|
|
||||||
|
GLuint program_id = 0;
|
||||||
|
const char *blt_vprogram =
|
||||||
|
"!!ARBvp1.0\n"
|
||||||
|
"PARAM c[1] = { { 1, 0.5 } };\n"
|
||||||
|
"MOV result.position, vertex.position;\n"
|
||||||
|
"MOV result.color, c[0].x;\n"
|
||||||
|
"MAD result.texcoord[0].y, -vertex.position, c[0], c[0];\n"
|
||||||
|
"MAD result.texcoord[0].x, vertex.position, c[0].y, c[0].y;\n"
|
||||||
|
"END\n";
|
||||||
|
|
||||||
|
GL_EXTCALL(glGenProgramsARB(1, &program_id));
|
||||||
|
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, program_id));
|
||||||
|
GL_EXTCALL(glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(blt_vprogram), blt_vprogram));
|
||||||
|
|
||||||
|
if (glGetError() == GL_INVALID_OPERATION) {
|
||||||
|
GLint pos;
|
||||||
|
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
|
||||||
|
FIXME("Vertex program error at position %d: %s\n", pos,
|
||||||
|
debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return program_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLuint create_arb_blt_fragment_program(IWineD3DDevice *iface) {
|
||||||
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
|
|
||||||
|
GLuint program_id = 0;
|
||||||
|
const char *blt_fprogram =
|
||||||
|
"!!ARBfp1.0\n"
|
||||||
|
"TEMP R0;\n"
|
||||||
|
"TEX R0.x, fragment.texcoord[0], texture[0], 2D;\n"
|
||||||
|
"MOV result.depth.z, R0.x;\n"
|
||||||
|
"END\n";
|
||||||
|
|
||||||
|
GL_EXTCALL(glGenProgramsARB(1, &program_id));
|
||||||
|
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, program_id));
|
||||||
|
GL_EXTCALL(glProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, strlen(blt_fprogram), blt_fprogram));
|
||||||
|
|
||||||
|
if (glGetError() == GL_INVALID_OPERATION) {
|
||||||
|
GLint pos;
|
||||||
|
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &pos);
|
||||||
|
FIXME("Fragment program error at position %d: %s\n", pos,
|
||||||
|
debugstr_a((const char *)glGetString(GL_PROGRAM_ERROR_STRING_ARB)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return program_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLhandleARB create_glsl_blt_shader(IWineD3DDevice *iface) {
|
||||||
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
|
|
||||||
|
GLhandleARB program_id;
|
||||||
|
GLhandleARB vshader_id, pshader_id;
|
||||||
|
const char *blt_vshader[] = {
|
||||||
|
"void main(void)\n"
|
||||||
|
"{\n"
|
||||||
|
" gl_Position = gl_Vertex;\n"
|
||||||
|
" gl_FrontColor = vec4(1.0);\n"
|
||||||
|
" gl_TexCoord[0].x = (gl_Vertex.x * 0.5) + 0.5;\n"
|
||||||
|
" gl_TexCoord[0].y = (-gl_Vertex.y * 0.5) + 0.5;\n"
|
||||||
|
"}\n"
|
||||||
|
};
|
||||||
|
|
||||||
|
const char *blt_pshader[] = {
|
||||||
|
"uniform sampler2D sampler;\n"
|
||||||
|
"void main(void)\n"
|
||||||
|
"{\n"
|
||||||
|
" gl_FragDepth = texture2D(sampler, gl_TexCoord[0].xy).x;\n"
|
||||||
|
"}\n"
|
||||||
|
};
|
||||||
|
|
||||||
|
vshader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB));
|
||||||
|
GL_EXTCALL(glShaderSourceARB(vshader_id, 1, blt_vshader, NULL));
|
||||||
|
GL_EXTCALL(glCompileShaderARB(vshader_id));
|
||||||
|
|
||||||
|
pshader_id = GL_EXTCALL(glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB));
|
||||||
|
GL_EXTCALL(glShaderSourceARB(pshader_id, 1, blt_pshader, NULL));
|
||||||
|
GL_EXTCALL(glCompileShaderARB(pshader_id));
|
||||||
|
|
||||||
|
program_id = GL_EXTCALL(glCreateProgramObjectARB());
|
||||||
|
GL_EXTCALL(glAttachObjectARB(program_id, vshader_id));
|
||||||
|
GL_EXTCALL(glAttachObjectARB(program_id, pshader_id));
|
||||||
|
GL_EXTCALL(glLinkProgramARB(program_id));
|
||||||
|
|
||||||
|
print_glsl_info_log(&GLINFO_LOCATION, program_id);
|
||||||
|
|
||||||
|
return program_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void depth_blt(IWineD3DDevice *iface, GLuint texture) {
|
||||||
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
|
BOOL glsl_mode = This->vs_selected_mode == SHADER_GLSL || This->ps_selected_mode == SHADER_GLSL;
|
||||||
|
|
||||||
|
glPushAttrib(GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
glDisable(GL_BLEND);
|
||||||
|
glDisable(GL_ALPHA_TEST);
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_ALWAYS);
|
||||||
|
|
||||||
|
GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB));
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
|
||||||
|
if (glsl_mode) {
|
||||||
|
static GLhandleARB program_id = 0;
|
||||||
|
static GLhandleARB loc = -1;
|
||||||
|
|
||||||
|
if (!program_id) {
|
||||||
|
program_id = create_glsl_blt_shader(iface);
|
||||||
|
loc = GL_EXTCALL(glGetUniformLocationARB(program_id, "sampler"));
|
||||||
|
}
|
||||||
|
|
||||||
|
GL_EXTCALL(glUseProgramObjectARB(program_id));
|
||||||
|
GL_EXTCALL(glUniform1iARB(loc, 0));
|
||||||
|
} else {
|
||||||
|
static GLuint vprogram_id = 0;
|
||||||
|
static GLuint fprogram_id = 0;
|
||||||
|
|
||||||
|
if (!vprogram_id) vprogram_id = create_arb_blt_vertex_program(iface);
|
||||||
|
GL_EXTCALL(glBindProgramARB(GL_VERTEX_PROGRAM_ARB, vprogram_id));
|
||||||
|
glEnable(GL_VERTEX_PROGRAM_ARB);
|
||||||
|
|
||||||
|
if (!fprogram_id) fprogram_id = create_arb_blt_fragment_program(iface);
|
||||||
|
GL_EXTCALL(glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, fprogram_id));
|
||||||
|
glEnable(GL_FRAGMENT_PROGRAM_ARB);
|
||||||
|
}
|
||||||
|
|
||||||
|
glBegin(GL_TRIANGLE_STRIP);
|
||||||
|
glVertex2f(-1.0f, -1.0f);
|
||||||
|
glVertex2f(1.0f, -1.0f);
|
||||||
|
glVertex2f(-1.0f, 1.0f);
|
||||||
|
glVertex2f(1.0f, 1.0f);
|
||||||
|
glEnd();
|
||||||
|
|
||||||
|
glPopAttrib();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void depth_copy(IWineD3DDevice *iface) {
|
||||||
|
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
|
||||||
|
IWineD3DSurfaceImpl *depth_stencil = (IWineD3DSurfaceImpl *)This->depthStencilBuffer;
|
||||||
|
|
||||||
|
/* TODO: Make this work for modes other than FBO */
|
||||||
|
if (wined3d_settings.offscreen_rendering_mode != ORM_FBO) return;
|
||||||
|
|
||||||
|
if (This->render_offscreen) {
|
||||||
|
static GLuint tmp_texture = 0;
|
||||||
|
|
||||||
|
TRACE("Copying onscreen depth buffer to offscreen surface\n");
|
||||||
|
|
||||||
|
if (!tmp_texture) {
|
||||||
|
glGenTextures(1, &tmp_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Note that we use depth_blt here as well, rather than glCopyTexImage2D
|
||||||
|
* directly on the FBO texture. That's because we need to flip. */
|
||||||
|
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tmp_texture);
|
||||||
|
glCopyTexImage2D(depth_stencil->glDescription.target,
|
||||||
|
depth_stencil->glDescription.level,
|
||||||
|
depth_stencil->glDescription.glFormatInternal,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
depth_stencil->currentDesc.Width,
|
||||||
|
depth_stencil->currentDesc.Height,
|
||||||
|
0);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_DEPTH_TEXTURE_MODE_ARB, GL_LUMINANCE);
|
||||||
|
|
||||||
|
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, This->fbo));
|
||||||
|
checkGLcall("glBindFramebuffer()");
|
||||||
|
depth_blt(iface, tmp_texture);
|
||||||
|
checkGLcall("depth_blt");
|
||||||
|
} else {
|
||||||
|
TRACE("Copying offscreen surface to onscreen depth buffer\n");
|
||||||
|
|
||||||
|
GL_EXTCALL(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||||
|
checkGLcall("glBindFramebuffer()");
|
||||||
|
depth_blt(iface, depth_stencil->glDescription.textureName);
|
||||||
|
checkGLcall("depth_blt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Routine common to the draw primitive and draw indexed primitive routines */
|
/* Routine common to the draw primitive and draw indexed primitive routines */
|
||||||
void drawPrimitive(IWineD3DDevice *iface,
|
void drawPrimitive(IWineD3DDevice *iface,
|
||||||
int PrimitiveType,
|
int PrimitiveType,
|
||||||
|
@ -2115,6 +2306,11 @@ void drawPrimitive(IWineD3DDevice *iface,
|
||||||
check_fbo_status(iface);
|
check_fbo_status(iface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (This->depth_copy_state == WINED3D_DCS_COPY) {
|
||||||
|
depth_copy(iface);
|
||||||
|
}
|
||||||
|
This->depth_copy_state = WINED3D_DCS_INITIAL;
|
||||||
|
|
||||||
/* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
|
/* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
|
||||||
* here simply check whether a shader was set, or the user disabled shaders */
|
* here simply check whether a shader was set, or the user disabled shaders */
|
||||||
if (This->vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
|
if (This->vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
|
||||||
|
|
|
@ -551,6 +551,7 @@ typedef struct IWineD3DDeviceImpl
|
||||||
|
|
||||||
/* For rendering to a texture using glCopyTexImage */
|
/* For rendering to a texture using glCopyTexImage */
|
||||||
BOOL render_offscreen;
|
BOOL render_offscreen;
|
||||||
|
WINED3D_DEPTHCOPYSTATE depth_copy_state;
|
||||||
GLuint fbo;
|
GLuint fbo;
|
||||||
|
|
||||||
/* Cursor management */
|
/* Cursor management */
|
||||||
|
|
|
@ -23,6 +23,13 @@
|
||||||
#ifndef __WINE_WINED3D_TYPES_INTERNAL_H
|
#ifndef __WINE_WINED3D_TYPES_INTERNAL_H
|
||||||
#define __WINE_WINED3D_TYPES_INTERNAL_H
|
#define __WINE_WINED3D_TYPES_INTERNAL_H
|
||||||
|
|
||||||
|
/* Depth copy state */
|
||||||
|
typedef enum {
|
||||||
|
WINED3D_DCS_INITIAL = 0,
|
||||||
|
WINED3D_DCS_COPY = 1,
|
||||||
|
WINED3D_DCS_NO_COPY = 2
|
||||||
|
} WINED3D_DEPTHCOPYSTATE;
|
||||||
|
|
||||||
/** DCL usage masks **/
|
/** DCL usage masks **/
|
||||||
#define WINED3DSP_DCL_USAGE_SHIFT 0
|
#define WINED3DSP_DCL_USAGE_SHIFT 0
|
||||||
#define WINED3DSP_DCL_USAGE_MASK 0x0000000f
|
#define WINED3DSP_DCL_USAGE_MASK 0x0000000f
|
||||||
|
|
Loading…
Reference in New Issue