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;
|
||||
IWineD3DSurfaceImpl *depth_stencil_impl = (IWineD3DSurfaceImpl *)depth_stencil;
|
||||
|
||||
This->depth_copy_state = WINED3D_DCS_NO_COPY;
|
||||
|
||||
bind_fbo(iface);
|
||||
|
||||
if (depth_stencil_impl) {
|
||||
|
@ -7275,6 +7277,9 @@ static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
|
|||
BOOL oldRecording;
|
||||
IWineD3DStateBlockImpl *oldUpdateStateBlock;
|
||||
|
||||
/* Nothing to update, return. */
|
||||
if (This->render_offscreen == isTexture) return;
|
||||
|
||||
/* Disable recording */
|
||||
oldUpdateStateBlock = This->updateStateBlock;
|
||||
oldRecording= This->isRecordingState;
|
||||
|
@ -7282,6 +7287,9 @@ static void device_render_to_texture(IWineD3DDeviceImpl* This, BOOL isTexture) {
|
|||
This->updateStateBlock = This->stateBlock;
|
||||
|
||||
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->proj_valid = FALSE;
|
||||
IWineD3DDevice_GetRenderState((IWineD3DDevice*) This, WINED3DRS_CULLMODE, &cullMode);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* Copyright 2002-2004 Raphael Junqueira
|
||||
* Copyright 2004 Christian Costa
|
||||
* Copyright 2005 Oliver Stieber
|
||||
* Copyright 2006 Henri Verbeet
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* 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 */
|
||||
void drawPrimitive(IWineD3DDevice *iface,
|
||||
int PrimitiveType,
|
||||
|
@ -2115,6 +2306,11 @@ void drawPrimitive(IWineD3DDevice *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 -
|
||||
* here simply check whether a shader was set, or the user disabled shaders */
|
||||
if (This->vs_selected_mode != SHADER_NONE && This->stateBlock->vertexShader &&
|
||||
|
|
|
@ -551,6 +551,7 @@ typedef struct IWineD3DDeviceImpl
|
|||
|
||||
/* For rendering to a texture using glCopyTexImage */
|
||||
BOOL render_offscreen;
|
||||
WINED3D_DEPTHCOPYSTATE depth_copy_state;
|
||||
GLuint fbo;
|
||||
|
||||
/* Cursor management */
|
||||
|
|
|
@ -23,6 +23,13 @@
|
|||
#ifndef __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 **/
|
||||
#define WINED3DSP_DCL_USAGE_SHIFT 0
|
||||
#define WINED3DSP_DCL_USAGE_MASK 0x0000000f
|
||||
|
|
Loading…
Reference in New Issue