Blitter handles color/depth texture copies.
This commit is contained in:
parent
d72610ba1b
commit
b9f9e1bb2b
|
@ -23,12 +23,15 @@ extern "C" WGLEWContext* wglewGetContext();
|
||||||
|
|
||||||
Blitter::Blitter()
|
Blitter::Blitter()
|
||||||
: vertex_program_(0),
|
: vertex_program_(0),
|
||||||
fragment_program_(0),
|
color_fragment_program_(0),
|
||||||
pipeline_(0),
|
depth_fragment_program_(0),
|
||||||
|
color_pipeline_(0),
|
||||||
|
depth_pipeline_(0),
|
||||||
vbo_(0),
|
vbo_(0),
|
||||||
vao_(0),
|
vao_(0),
|
||||||
nearest_sampler_(0),
|
nearest_sampler_(0),
|
||||||
linear_sampler_(0) {}
|
linear_sampler_(0),
|
||||||
|
scratch_framebuffer_(0) {}
|
||||||
|
|
||||||
Blitter::~Blitter() = default;
|
Blitter::~Blitter() = default;
|
||||||
|
|
||||||
|
@ -43,7 +46,7 @@ precision highp int; \n\
|
||||||
layout(std140, column_major) uniform; \n\
|
layout(std140, column_major) uniform; \n\
|
||||||
layout(std430, column_major) buffer; \n\
|
layout(std430, column_major) buffer; \n\
|
||||||
struct VertexData { \n\
|
struct VertexData { \n\
|
||||||
vec2 uv; \n\
|
vec2 uv; \n\
|
||||||
}; \n\
|
}; \n\
|
||||||
";
|
";
|
||||||
const std::string vs_source = header +
|
const std::string vs_source = header +
|
||||||
|
@ -55,37 +58,51 @@ out gl_PerVertex { \n\
|
||||||
float gl_ClipDistance[]; \n\
|
float gl_ClipDistance[]; \n\
|
||||||
}; \n\
|
}; \n\
|
||||||
struct VertexFetch { \n\
|
struct VertexFetch { \n\
|
||||||
vec2 pos; \n\
|
vec2 pos; \n\
|
||||||
};\n\
|
};\n\
|
||||||
layout(location = 0) in VertexFetch vfetch; \n\
|
layout(location = 0) in VertexFetch vfetch; \n\
|
||||||
layout(location = 0) out VertexData vtx; \n\
|
layout(location = 0) out VertexData vtx; \n\
|
||||||
void main() { \n\
|
void main() { \n\
|
||||||
gl_Position = vec4(vfetch.pos.xy * vec2(2.0, 2.0) - vec2(1.0, 1.0), 0.0, 1.0); \n\
|
gl_Position = vec4(vfetch.pos.xy * vec2(2.0, -2.0) - vec2(1.0, -1.0), 0.0, 1.0); \n\
|
||||||
vtx.uv = vfetch.pos.xy * src_uv_params.zw + src_uv_params.xy; \n\
|
vtx.uv = vfetch.pos.xy * src_uv_params.zw + src_uv_params.xy; \n\
|
||||||
} \n\
|
} \n\
|
||||||
";
|
";
|
||||||
const std::string fs_source = header +
|
const std::string color_fs_source = header +
|
||||||
"\n\
|
"\n\
|
||||||
layout(location = 1) uniform sampler2D src_texture; \n\
|
layout(location = 1) uniform sampler2D src_texture; \n\
|
||||||
layout(location = 0) in VertexData vtx; \n\
|
layout(location = 0) in VertexData vtx; \n\
|
||||||
layout(location = 0) out vec4 oC; \n\
|
layout(location = 0) out vec4 oC; \n\
|
||||||
void main() { \n\
|
void main() { \n\
|
||||||
vec4 color = texture(src_texture, vtx.uv); \n\
|
oC = texture(src_texture, vtx.uv); \n\
|
||||||
oC = color; \n\
|
} \n\
|
||||||
|
";
|
||||||
|
const std::string depth_fs_source = header +
|
||||||
|
"\n\
|
||||||
|
layout(location = 1) uniform sampler2D src_texture; \n\
|
||||||
|
layout(location = 0) in VertexData vtx; \n\
|
||||||
|
layout(location = 0) out vec4 oC; \n\
|
||||||
|
void main() { \n\
|
||||||
|
vec4 c = texture(src_texture, vtx.uv); \n\
|
||||||
|
gl_FragDepth = c.r; \n\
|
||||||
} \n\
|
} \n\
|
||||||
";
|
";
|
||||||
|
|
||||||
auto vs_source_str = vs_source.c_str();
|
auto vs_source_str = vs_source.c_str();
|
||||||
vertex_program_ = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vs_source_str);
|
vertex_program_ = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &vs_source_str);
|
||||||
auto fs_source_str = fs_source.c_str();
|
auto color_fs_source_str = color_fs_source.c_str();
|
||||||
fragment_program_ =
|
color_fragment_program_ =
|
||||||
glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &fs_source_str);
|
glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &color_fs_source_str);
|
||||||
char log[2048];
|
auto depth_fs_source_str = depth_fs_source.c_str();
|
||||||
GLsizei log_length;
|
depth_fragment_program_ =
|
||||||
glGetProgramInfoLog(vertex_program_, 2048, &log_length, log);
|
glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &depth_fs_source_str);
|
||||||
glCreateProgramPipelines(1, &pipeline_);
|
glCreateProgramPipelines(1, &color_pipeline_);
|
||||||
glUseProgramStages(pipeline_, GL_VERTEX_SHADER_BIT, vertex_program_);
|
glUseProgramStages(color_pipeline_, GL_VERTEX_SHADER_BIT, vertex_program_);
|
||||||
glUseProgramStages(pipeline_, GL_FRAGMENT_SHADER_BIT, fragment_program_);
|
glUseProgramStages(color_pipeline_, GL_FRAGMENT_SHADER_BIT,
|
||||||
|
color_fragment_program_);
|
||||||
|
glCreateProgramPipelines(1, &depth_pipeline_);
|
||||||
|
glUseProgramStages(depth_pipeline_, GL_VERTEX_SHADER_BIT, vertex_program_);
|
||||||
|
glUseProgramStages(depth_pipeline_, GL_FRAGMENT_SHADER_BIT,
|
||||||
|
depth_fragment_program_);
|
||||||
|
|
||||||
glCreateBuffers(1, &vbo_);
|
glCreateBuffers(1, &vbo_);
|
||||||
static const GLfloat vbo_data[] = {
|
static const GLfloat vbo_data[] = {
|
||||||
|
@ -110,38 +127,96 @@ oC = color; \n\
|
||||||
glSamplerParameteri(linear_sampler_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glSamplerParameteri(linear_sampler_, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glSamplerParameteri(linear_sampler_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glSamplerParameteri(linear_sampler_, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
glCreateFramebuffers(1, &scratch_framebuffer_);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blitter::Shutdown() {
|
void Blitter::Shutdown() {
|
||||||
if (vertex_program_) {
|
glDeleteFramebuffers(1, &scratch_framebuffer_);
|
||||||
glDeleteProgram(vertex_program_);
|
glDeleteProgram(vertex_program_);
|
||||||
}
|
glDeleteProgram(color_fragment_program_);
|
||||||
if (fragment_program_) {
|
glDeleteProgram(depth_fragment_program_);
|
||||||
glDeleteProgram(fragment_program_);
|
glDeleteProgramPipelines(1, &color_pipeline_);
|
||||||
}
|
glDeleteProgramPipelines(1, &depth_pipeline_);
|
||||||
if (pipeline_) {
|
|
||||||
glDeleteProgramPipelines(1, &pipeline_);
|
|
||||||
}
|
|
||||||
if (vbo_) {
|
|
||||||
glDeleteBuffers(1, &vbo_);
|
glDeleteBuffers(1, &vbo_);
|
||||||
}
|
|
||||||
if (vao_) {
|
|
||||||
glDeleteVertexArrays(1, &vao_);
|
glDeleteVertexArrays(1, &vao_);
|
||||||
}
|
|
||||||
if (nearest_sampler_) {
|
|
||||||
glDeleteSamplers(1, &nearest_sampler_);
|
glDeleteSamplers(1, &nearest_sampler_);
|
||||||
}
|
|
||||||
if (linear_sampler_) {
|
|
||||||
glDeleteSamplers(1, &linear_sampler_);
|
glDeleteSamplers(1, &linear_sampler_);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SavedState {
|
||||||
|
GLboolean scissor_test_enabled;
|
||||||
|
GLboolean depth_test_enabled;
|
||||||
|
GLboolean depth_mask_enabled;
|
||||||
|
GLint depth_func;
|
||||||
|
GLboolean stencil_test_enabled;
|
||||||
|
GLboolean cull_face_enabled;
|
||||||
|
GLint cull_face;
|
||||||
|
GLint front_face;
|
||||||
|
GLint polygon_mode;
|
||||||
|
GLboolean color_mask_0_enabled[4];
|
||||||
|
GLboolean blend_0_enabled;
|
||||||
|
GLint draw_buffer;
|
||||||
|
GLfloat viewport[4];
|
||||||
|
GLint program_pipeline;
|
||||||
|
GLint vertex_array;
|
||||||
|
GLint texture_0;
|
||||||
|
GLint sampler_0;
|
||||||
|
|
||||||
|
void Save() {
|
||||||
|
scissor_test_enabled = glIsEnabled(GL_SCISSOR_TEST);
|
||||||
|
depth_test_enabled = glIsEnabled(GL_DEPTH_TEST);
|
||||||
|
glGetBooleanv(GL_DEPTH_WRITEMASK, &depth_mask_enabled);
|
||||||
|
glGetIntegerv(GL_DEPTH_FUNC, &depth_func);
|
||||||
|
stencil_test_enabled = glIsEnabled(GL_STENCIL_TEST);
|
||||||
|
cull_face_enabled = glIsEnabled(GL_CULL_FACE);
|
||||||
|
glGetIntegerv(GL_CULL_FACE_MODE, &cull_face);
|
||||||
|
glGetIntegerv(GL_FRONT_FACE, &front_face);
|
||||||
|
glGetIntegerv(GL_POLYGON_MODE, &polygon_mode);
|
||||||
|
glGetBooleani_v(GL_COLOR_WRITEMASK, 0, (GLboolean*)&color_mask_0_enabled);
|
||||||
|
blend_0_enabled = glIsEnabledi(GL_BLEND, 0);
|
||||||
|
glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &draw_buffer);
|
||||||
|
glGetFloati_v(GL_VIEWPORT, 0, viewport);
|
||||||
|
glGetIntegerv(GL_PROGRAM_PIPELINE_BINDING, &program_pipeline);
|
||||||
|
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &vertex_array);
|
||||||
|
glGetIntegerv(GL_TEXTURE_BINDING_2D, &texture_0);
|
||||||
|
glGetIntegeri_v(GL_SAMPLER_BINDING, 0, &sampler_0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Restore() {
|
||||||
|
scissor_test_enabled ? glEnable(GL_SCISSOR_TEST)
|
||||||
|
: glDisable(GL_SCISSOR_TEST);
|
||||||
|
depth_test_enabled ? glEnable(GL_DEPTH_TEST) : glDisable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(depth_mask_enabled);
|
||||||
|
glDepthFunc(depth_func);
|
||||||
|
stencil_test_enabled ? glEnable(GL_STENCIL_TEST)
|
||||||
|
: glDisable(GL_STENCIL_TEST);
|
||||||
|
cull_face_enabled ? glEnable(GL_CULL_FACE) : glDisable(GL_CULL_FACE);
|
||||||
|
glCullFace(cull_face);
|
||||||
|
glFrontFace(front_face);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, polygon_mode);
|
||||||
|
glColorMaski(0, color_mask_0_enabled[0], color_mask_0_enabled[1],
|
||||||
|
color_mask_0_enabled[2], color_mask_0_enabled[3]);
|
||||||
|
blend_0_enabled ? glEnablei(GL_BLEND, 0) : glDisablei(GL_BLEND, 0);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw_buffer);
|
||||||
|
glViewportIndexedf(0, viewport[0], viewport[1], viewport[2], viewport[3]);
|
||||||
|
glBindProgramPipeline(program_pipeline);
|
||||||
|
glBindVertexArray(vertex_array);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, texture_0);
|
||||||
|
glBindSampler(0, sampler_0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void Blitter::Draw(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
void Blitter::Draw(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
||||||
uint32_t src_width, uint32_t src_height, GLenum filter) {
|
uint32_t src_width, uint32_t src_height, GLenum filter) {
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
glDisable(GL_STENCIL_TEST);
|
||||||
glDisablei(GL_BLEND, 0);
|
glDisablei(GL_BLEND, 0);
|
||||||
glDisable(GL_DEPTH_TEST);
|
glEnable(GL_CULL_FACE);
|
||||||
glBindProgramPipeline(pipeline_);
|
glCullFace(GL_BACK);
|
||||||
|
glFrontFace(GL_CW);
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
glBindVertexArray(vao_);
|
glBindVertexArray(vao_);
|
||||||
glBindTextures(0, 1, &src_texture);
|
glBindTextures(0, 1, &src_texture);
|
||||||
switch (filter) {
|
switch (filter) {
|
||||||
|
@ -167,12 +242,6 @@ void Blitter::Draw(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
||||||
src_height / float(src_texture_height));
|
src_height / float(src_texture_height));
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||||
|
|
||||||
glBindProgramPipeline(0);
|
|
||||||
glBindVertexArray(0);
|
|
||||||
GLuint zero = 0;
|
|
||||||
glBindTextures(0, 1, &zero);
|
|
||||||
glBindSampler(0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blitter::BlitTexture2D(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
void Blitter::BlitTexture2D(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
||||||
|
@ -180,17 +249,70 @@ void Blitter::BlitTexture2D(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
||||||
uint32_t dest_x, uint32_t dest_y,
|
uint32_t dest_x, uint32_t dest_y,
|
||||||
uint32_t dest_width, uint32_t dest_height,
|
uint32_t dest_width, uint32_t dest_height,
|
||||||
GLenum filter) {
|
GLenum filter) {
|
||||||
|
SavedState state;
|
||||||
|
state.Save();
|
||||||
|
|
||||||
glViewport(dest_x, dest_y, dest_width, dest_height);
|
glViewport(dest_x, dest_y, dest_width, dest_height);
|
||||||
|
glColorMaski(0, true, true, true, true);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(false);
|
||||||
|
glBindProgramPipeline(color_pipeline_);
|
||||||
|
|
||||||
Draw(src_texture, src_x, src_y, src_width, src_height, filter);
|
Draw(src_texture, src_x, src_y, src_width, src_height, filter);
|
||||||
|
|
||||||
|
state.Restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blitter::CopyTexture2D(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
void Blitter::CopyColorTexture2D(GLuint src_texture, uint32_t src_x,
|
||||||
uint32_t src_width, uint32_t src_height,
|
uint32_t src_y, uint32_t src_width,
|
||||||
uint32_t dest_texture, uint32_t dest_x,
|
uint32_t src_height, uint32_t dest_texture,
|
||||||
uint32_t dest_y, uint32_t dest_width,
|
uint32_t dest_x, uint32_t dest_y,
|
||||||
uint32_t dest_height, GLenum filter) {
|
uint32_t dest_width, uint32_t dest_height,
|
||||||
|
GLenum filter) {
|
||||||
|
SavedState state;
|
||||||
|
state.Save();
|
||||||
|
|
||||||
glViewport(dest_x, dest_y, dest_width, dest_height);
|
glViewport(dest_x, dest_y, dest_width, dest_height);
|
||||||
//
|
glColorMaski(0, true, true, true, true);
|
||||||
|
glDisable(GL_DEPTH_TEST);
|
||||||
|
glDepthMask(false);
|
||||||
|
glBindProgramPipeline(color_pipeline_);
|
||||||
|
|
||||||
|
glNamedFramebufferTexture(scratch_framebuffer_, GL_COLOR_ATTACHMENT0,
|
||||||
|
dest_texture, 0);
|
||||||
|
glNamedFramebufferDrawBuffer(scratch_framebuffer_, GL_COLOR_ATTACHMENT0);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, scratch_framebuffer_);
|
||||||
|
Draw(src_texture, src_x, src_y, src_width, src_height, filter);
|
||||||
|
glNamedFramebufferDrawBuffer(scratch_framebuffer_, GL_NONE);
|
||||||
|
glNamedFramebufferTexture(scratch_framebuffer_, GL_COLOR_ATTACHMENT0, GL_NONE,
|
||||||
|
0);
|
||||||
|
|
||||||
|
state.Restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Blitter::CopyDepthTexture(GLuint src_texture, uint32_t src_x,
|
||||||
|
uint32_t src_y, uint32_t src_width,
|
||||||
|
uint32_t src_height, uint32_t dest_texture,
|
||||||
|
uint32_t dest_x, uint32_t dest_y,
|
||||||
|
uint32_t dest_width, uint32_t dest_height) {
|
||||||
|
SavedState state;
|
||||||
|
state.Save();
|
||||||
|
|
||||||
|
glViewport(dest_x, dest_y, dest_width, dest_height);
|
||||||
|
glColorMaski(0, false, false, false, false);
|
||||||
|
glEnable(GL_DEPTH_TEST);
|
||||||
|
glDepthFunc(GL_ALWAYS);
|
||||||
|
glDepthMask(true);
|
||||||
|
glBindProgramPipeline(depth_pipeline_);
|
||||||
|
|
||||||
|
glNamedFramebufferTexture(scratch_framebuffer_, GL_DEPTH_STENCIL_ATTACHMENT,
|
||||||
|
dest_texture, 0);
|
||||||
|
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, scratch_framebuffer_);
|
||||||
|
Draw(src_texture, src_x, src_y, src_width, src_height, GL_NEAREST);
|
||||||
|
glNamedFramebufferTexture(scratch_framebuffer_, GL_DEPTH_STENCIL_ATTACHMENT,
|
||||||
|
GL_NONE, 0);
|
||||||
|
|
||||||
|
state.Restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace gl4
|
} // namespace gl4
|
||||||
|
|
|
@ -32,22 +32,30 @@ class Blitter {
|
||||||
uint32_t dest_y, uint32_t dest_width, uint32_t dest_height,
|
uint32_t dest_y, uint32_t dest_width, uint32_t dest_height,
|
||||||
GLenum filter);
|
GLenum filter);
|
||||||
|
|
||||||
void CopyTexture2D(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
void CopyColorTexture2D(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
||||||
|
uint32_t src_width, uint32_t src_height,
|
||||||
|
uint32_t dest_texture, uint32_t dest_x,
|
||||||
|
uint32_t dest_y, uint32_t dest_width,
|
||||||
|
uint32_t dest_height, GLenum filter);
|
||||||
|
void CopyDepthTexture(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
||||||
uint32_t src_width, uint32_t src_height,
|
uint32_t src_width, uint32_t src_height,
|
||||||
uint32_t dest_texture, uint32_t dest_x, uint32_t dest_y,
|
uint32_t dest_texture, uint32_t dest_x, uint32_t dest_y,
|
||||||
uint32_t dest_width, uint32_t dest_height, GLenum filter);
|
uint32_t dest_width, uint32_t dest_height);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Draw(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
void Draw(GLuint src_texture, uint32_t src_x, uint32_t src_y,
|
||||||
uint32_t src_width, uint32_t src_height, GLenum filter);
|
uint32_t src_width, uint32_t src_height, GLenum filter);
|
||||||
|
|
||||||
GLuint vertex_program_;
|
GLuint vertex_program_;
|
||||||
GLuint fragment_program_;
|
GLuint color_fragment_program_;
|
||||||
GLuint pipeline_;
|
GLuint depth_fragment_program_;
|
||||||
|
GLuint color_pipeline_;
|
||||||
|
GLuint depth_pipeline_;
|
||||||
GLuint vbo_;
|
GLuint vbo_;
|
||||||
GLuint vao_;
|
GLuint vao_;
|
||||||
GLuint nearest_sampler_;
|
GLuint nearest_sampler_;
|
||||||
GLuint linear_sampler_;
|
GLuint linear_sampler_;
|
||||||
|
GLuint scratch_framebuffer_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace gl4
|
} // namespace gl4
|
||||||
|
|
|
@ -2472,7 +2472,7 @@ bool CommandProcessor::IssueCopy() {
|
||||||
glPixelStorei(GL_PACK_SWAP_BYTES, GL_TRUE);
|
glPixelStorei(GL_PACK_SWAP_BYTES, GL_TRUE);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//assert_unhandled_case(copy_dest_endian);
|
// assert_unhandled_case(copy_dest_endian);
|
||||||
glPixelStorei(GL_PACK_SWAP_BYTES, GL_TRUE);
|
glPixelStorei(GL_PACK_SWAP_BYTES, GL_TRUE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2498,29 +2498,26 @@ bool CommandProcessor::IssueCopy() {
|
||||||
uint32_t h = copy_dest_height;
|
uint32_t h = copy_dest_height;
|
||||||
|
|
||||||
// Make active so glReadPixels reads from us.
|
// Make active so glReadPixels reads from us.
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, source_framebuffer->framebuffer);
|
|
||||||
switch (copy_command) {
|
switch (copy_command) {
|
||||||
case CopyCommand::kRaw: {
|
case CopyCommand::kRaw: {
|
||||||
// This performs a byte-for-byte copy of the textures from src to dest
|
// This performs a byte-for-byte copy of the textures from src to dest
|
||||||
// with no conversion. Byte swapping may still occur.
|
// with no conversion. Byte swapping may still occur.
|
||||||
if (copy_src_select <= 3) {
|
if (copy_src_select <= 3) {
|
||||||
// Source from a bound render target.
|
// Source from a bound render target.
|
||||||
glNamedFramebufferReadBuffer(source_framebuffer->framebuffer,
|
|
||||||
GL_COLOR_ATTACHMENT0 + copy_src_select);
|
|
||||||
// TODO(benvanik): RAW copy.
|
// TODO(benvanik): RAW copy.
|
||||||
last_framebuffer_texture_ = texture_cache_.CopyReadBufferTexture(
|
last_framebuffer_texture_ = texture_cache_.CopyTexture(
|
||||||
copy_dest_base, x, y, w, h,
|
context_->blitter(), copy_dest_base, x, y, w, h,
|
||||||
ColorFormatToTextureFormat(copy_dest_format),
|
ColorFormatToTextureFormat(copy_dest_format),
|
||||||
copy_dest_swap ? true : false);
|
copy_dest_swap ? true : false, color_targets[copy_src_select]);
|
||||||
if (!FLAGS_disable_framebuffer_readback) {
|
if (!FLAGS_disable_framebuffer_readback) {
|
||||||
// glReadPixels(x, y, w, h, read_format, read_type, ptr);
|
// glReadPixels(x, y, w, h, read_format, read_type, ptr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Source from the bound depth/stencil target.
|
// Source from the bound depth/stencil target.
|
||||||
// TODO(benvanik): RAW copy.
|
// TODO(benvanik): RAW copy.
|
||||||
texture_cache_.CopyReadBufferTexture(copy_dest_base, x, y, w, h,
|
texture_cache_.CopyTexture(context_->blitter(), copy_dest_base, x, y, w,
|
||||||
src_format,
|
h, src_format, copy_dest_swap ? true : false,
|
||||||
copy_dest_swap ? true : false);
|
depth_target);
|
||||||
if (!FLAGS_disable_framebuffer_readback) {
|
if (!FLAGS_disable_framebuffer_readback) {
|
||||||
// glReadPixels(x, y, w, h, GL_DEPTH_STENCIL, read_type, ptr);
|
// glReadPixels(x, y, w, h, GL_DEPTH_STENCIL, read_type, ptr);
|
||||||
}
|
}
|
||||||
|
@ -2530,22 +2527,20 @@ bool CommandProcessor::IssueCopy() {
|
||||||
case CopyCommand::kConvert: {
|
case CopyCommand::kConvert: {
|
||||||
if (copy_src_select <= 3) {
|
if (copy_src_select <= 3) {
|
||||||
// Source from a bound render target.
|
// Source from a bound render target.
|
||||||
glNamedFramebufferReadBuffer(source_framebuffer->framebuffer,
|
|
||||||
GL_COLOR_ATTACHMENT0 + copy_src_select);
|
|
||||||
// Either copy the readbuffer into an existing texture or create a new
|
// Either copy the readbuffer into an existing texture or create a new
|
||||||
// one in the cache so we can service future upload requests.
|
// one in the cache so we can service future upload requests.
|
||||||
last_framebuffer_texture_ = texture_cache_.CopyReadBufferTexture(
|
last_framebuffer_texture_ = texture_cache_.ConvertTexture(
|
||||||
copy_dest_base, x, y, w, h,
|
context_->blitter(), copy_dest_base, x, y, w, h,
|
||||||
ColorFormatToTextureFormat(copy_dest_format),
|
ColorFormatToTextureFormat(copy_dest_format),
|
||||||
copy_dest_swap ? true : false);
|
copy_dest_swap ? true : false, color_targets[copy_src_select]);
|
||||||
if (!FLAGS_disable_framebuffer_readback) {
|
if (!FLAGS_disable_framebuffer_readback) {
|
||||||
// glReadPixels(x, y, w, h, read_format, read_type, ptr);
|
// glReadPixels(x, y, w, h, read_format, read_type, ptr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Source from the bound depth/stencil target.
|
// Source from the bound depth/stencil target.
|
||||||
texture_cache_.CopyReadBufferTexture(copy_dest_base, x, y, w, h,
|
texture_cache_.ConvertTexture(
|
||||||
src_format,
|
context_->blitter(), copy_dest_base, x, y, w, h, src_format,
|
||||||
copy_dest_swap ? true : false);
|
copy_dest_swap ? true : false, depth_target);
|
||||||
if (!FLAGS_disable_framebuffer_readback) {
|
if (!FLAGS_disable_framebuffer_readback) {
|
||||||
// glReadPixels(x, y, w, h, GL_DEPTH_STENCIL, read_type, ptr);
|
// glReadPixels(x, y, w, h, GL_DEPTH_STENCIL, read_type, ptr);
|
||||||
}
|
}
|
||||||
|
@ -2558,7 +2553,6 @@ bool CommandProcessor::IssueCopy() {
|
||||||
// assert_unhandled_case(copy_command);
|
// assert_unhandled_case(copy_command);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
|
||||||
|
|
||||||
// Perform any requested clears.
|
// Perform any requested clears.
|
||||||
uint32_t copy_depth_clear = regs[XE_GPU_REG_RB_DEPTH_CLEAR].u32;
|
uint32_t copy_depth_clear = regs[XE_GPU_REG_RB_DEPTH_CLEAR].u32;
|
||||||
|
|
|
@ -33,112 +33,112 @@ struct TextureConfig {
|
||||||
// http://dench.flatlib.jp/opengl/textures
|
// http://dench.flatlib.jp/opengl/textures
|
||||||
// http://fossies.org/linux/WebKit/Source/ThirdParty/ANGLE/src/libGLESv2/formatutils.cpp
|
// http://fossies.org/linux/WebKit/Source/ThirdParty/ANGLE/src/libGLESv2/formatutils.cpp
|
||||||
static const TextureConfig texture_configs[64] = {
|
static const TextureConfig texture_configs[64] = {
|
||||||
{ TextureFormat::k_1_REVERSE, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_1_REVERSE, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_1, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM },
|
{TextureFormat::k_1, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_8, GL_R8, GL_RED, GL_UNSIGNED_BYTE },
|
{TextureFormat::k_8, GL_R8, GL_RED, GL_UNSIGNED_BYTE},
|
||||||
{ TextureFormat::k_1_5_5_5, GL_RGB5_A1, GL_RGBA,
|
{TextureFormat::k_1_5_5_5, GL_RGB5_A1, GL_RGBA,
|
||||||
GL_UNSIGNED_SHORT_1_5_5_5_REV },
|
GL_UNSIGNED_SHORT_1_5_5_5_REV},
|
||||||
{ TextureFormat::k_5_6_5, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 },
|
{TextureFormat::k_5_6_5, GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5},
|
||||||
{ TextureFormat::k_6_5_5, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM },
|
{TextureFormat::k_6_5_5, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_8_8_8_8, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE },
|
{TextureFormat::k_8_8_8_8, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE},
|
||||||
{ TextureFormat::k_2_10_10_10, GL_RGB10_A2, GL_RGBA,
|
{TextureFormat::k_2_10_10_10, GL_RGB10_A2, GL_RGBA,
|
||||||
GL_UNSIGNED_INT_2_10_10_10_REV },
|
GL_UNSIGNED_INT_2_10_10_10_REV},
|
||||||
{ TextureFormat::k_8_A, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM },
|
{TextureFormat::k_8_A, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_8_B, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM },
|
{TextureFormat::k_8_B, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_8_8, GL_RG8, GL_RG, GL_UNSIGNED_BYTE },
|
{TextureFormat::k_8_8, GL_RG8, GL_RG, GL_UNSIGNED_BYTE},
|
||||||
{ TextureFormat::k_Cr_Y1_Cb_Y0, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_Cr_Y1_Cb_Y0, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_Y1_Cr_Y0_Cb, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_Y1_Cr_Y0_Cb, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::kUnknown, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::kUnknown, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_8_8_8_8_A, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_8_8_8_8_A, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_4_4_4_4, GL_RGBA4, GL_RGBA,
|
{TextureFormat::k_4_4_4_4, GL_RGBA4, GL_RGBA,
|
||||||
GL_UNSIGNED_SHORT_4_4_4_4_REV },
|
GL_UNSIGNED_SHORT_4_4_4_4_REV},
|
||||||
{ TextureFormat::k_10_11_11, GL_R11F_G11F_B10F, GL_RGB,
|
{TextureFormat::k_10_11_11, GL_R11F_G11F_B10F, GL_RGB,
|
||||||
GL_UNSIGNED_INT_10F_11F_11F_REV }, // ?
|
GL_UNSIGNED_INT_10F_11F_11F_REV}, // ?
|
||||||
{ TextureFormat::k_11_11_10, GL_R11F_G11F_B10F, GL_RGB,
|
{TextureFormat::k_11_11_10, GL_R11F_G11F_B10F, GL_RGB,
|
||||||
GL_UNSIGNED_INT_10F_11F_11F_REV }, // ?
|
GL_UNSIGNED_INT_10F_11F_11F_REV}, // ?
|
||||||
{ TextureFormat::k_DXT1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
|
{TextureFormat::k_DXT1, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
|
||||||
GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE },
|
GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE},
|
||||||
{ TextureFormat::k_DXT2_3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
|
{TextureFormat::k_DXT2_3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
|
||||||
GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_UNSIGNED_BYTE },
|
GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_UNSIGNED_BYTE},
|
||||||
{ TextureFormat::k_DXT4_5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
|
{TextureFormat::k_DXT4_5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
|
||||||
GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_UNSIGNED_BYTE },
|
GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_UNSIGNED_BYTE},
|
||||||
{ TextureFormat::kUnknown, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::kUnknown, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_24_8, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL,
|
{TextureFormat::k_24_8, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL,
|
||||||
GL_UNSIGNED_INT_24_8 },
|
GL_UNSIGNED_INT_24_8},
|
||||||
{ TextureFormat::k_24_8_FLOAT, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL,
|
{TextureFormat::k_24_8_FLOAT, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL,
|
||||||
GL_FLOAT_32_UNSIGNED_INT_24_8_REV },
|
GL_FLOAT_32_UNSIGNED_INT_24_8_REV},
|
||||||
{ TextureFormat::k_16, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM },
|
{TextureFormat::k_16, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_16_16, GL_RG16, GL_RG, GL_UNSIGNED_SHORT },
|
{TextureFormat::k_16_16, GL_RG16, GL_RG, GL_UNSIGNED_SHORT},
|
||||||
{ TextureFormat::k_16_16_16_16, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_16_16_16_16, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_16_EXPAND, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_16_EXPAND, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_16_16_EXPAND, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_16_16_EXPAND, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_16_16_16_16_EXPAND, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_16_16_16_16_EXPAND, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_16_FLOAT, GL_R16F, GL_RED, GL_HALF_FLOAT },
|
{TextureFormat::k_16_FLOAT, GL_R16F, GL_RED, GL_HALF_FLOAT},
|
||||||
{ TextureFormat::k_16_16_FLOAT, GL_RG16F, GL_RG, GL_HALF_FLOAT },
|
{TextureFormat::k_16_16_FLOAT, GL_RG16F, GL_RG, GL_HALF_FLOAT},
|
||||||
{ TextureFormat::k_16_16_16_16_FLOAT, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT },
|
{TextureFormat::k_16_16_16_16_FLOAT, GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT},
|
||||||
{ TextureFormat::k_32, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM },
|
{TextureFormat::k_32, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_32_32, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM },
|
{TextureFormat::k_32_32, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_32_32_32_32, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_32_32_32_32, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_32_FLOAT, GL_R32F, GL_RED, GL_FLOAT },
|
{TextureFormat::k_32_FLOAT, GL_R32F, GL_RED, GL_FLOAT},
|
||||||
{ TextureFormat::k_32_32_FLOAT, GL_RG32F, GL_RG, GL_FLOAT },
|
{TextureFormat::k_32_32_FLOAT, GL_RG32F, GL_RG, GL_FLOAT},
|
||||||
{ TextureFormat::k_32_32_32_32_FLOAT, GL_RGBA32F, GL_RGBA, GL_FLOAT },
|
{TextureFormat::k_32_32_32_32_FLOAT, GL_RGBA32F, GL_RGBA, GL_FLOAT},
|
||||||
{ TextureFormat::k_32_AS_8, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_32_AS_8, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_32_AS_8_8, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_32_AS_8_8, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_16_MPEG, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_16_MPEG, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_16_16_MPEG, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_16_16_MPEG, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_8_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_8_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_32_AS_8_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_32_AS_8_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_32_AS_8_8_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_32_AS_8_8_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_16_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_16_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_16_MPEG_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_16_MPEG_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_16_16_MPEG_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_16_16_MPEG_INTERLACED, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_DXN, GL_COMPRESSED_RG_RGTC2, GL_COMPRESSED_RG_RGTC2,
|
{TextureFormat::k_DXN, GL_COMPRESSED_RG_RGTC2, GL_COMPRESSED_RG_RGTC2,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_8_8_8_8_AS_16_16_16_16, GL_RGBA8, GL_RGBA,
|
{TextureFormat::k_8_8_8_8_AS_16_16_16_16, GL_RGBA8, GL_RGBA,
|
||||||
GL_UNSIGNED_BYTE },
|
GL_UNSIGNED_BYTE},
|
||||||
{ TextureFormat::k_DXT1_AS_16_16_16_16, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
|
{TextureFormat::k_DXT1_AS_16_16_16_16, GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
|
||||||
GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE },
|
GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE},
|
||||||
{ TextureFormat::k_DXT2_3_AS_16_16_16_16, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
|
{TextureFormat::k_DXT2_3_AS_16_16_16_16, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
|
||||||
GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_UNSIGNED_BYTE },
|
GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_UNSIGNED_BYTE},
|
||||||
{ TextureFormat::k_DXT4_5_AS_16_16_16_16, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
|
{TextureFormat::k_DXT4_5_AS_16_16_16_16, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
|
||||||
GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_UNSIGNED_BYTE },
|
GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_UNSIGNED_BYTE},
|
||||||
{ TextureFormat::k_2_10_10_10_AS_16_16_16_16, GL_RGB10_A2, GL_RGBA,
|
{TextureFormat::k_2_10_10_10_AS_16_16_16_16, GL_RGB10_A2, GL_RGBA,
|
||||||
GL_UNSIGNED_INT_2_10_10_10_REV },
|
GL_UNSIGNED_INT_2_10_10_10_REV},
|
||||||
{ TextureFormat::k_10_11_11_AS_16_16_16_16, GL_R11F_G11F_B10F, GL_RGB,
|
{TextureFormat::k_10_11_11_AS_16_16_16_16, GL_R11F_G11F_B10F, GL_RGB,
|
||||||
GL_UNSIGNED_INT_10F_11F_11F_REV },
|
GL_UNSIGNED_INT_10F_11F_11F_REV},
|
||||||
{ TextureFormat::k_11_11_10_AS_16_16_16_16, GL_R11F_G11F_B10F,
|
{TextureFormat::k_11_11_10_AS_16_16_16_16, GL_R11F_G11F_B10F,
|
||||||
GL_INVALID_ENUM, GL_INVALID_ENUM },
|
GL_INVALID_ENUM, GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_32_32_32_FLOAT, GL_RGB32F, GL_RGB, GL_FLOAT },
|
{TextureFormat::k_32_32_32_FLOAT, GL_RGB32F, GL_RGB, GL_FLOAT},
|
||||||
{ TextureFormat::k_DXT3A, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM },
|
{TextureFormat::k_DXT3A, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_DXT5A, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM },
|
{TextureFormat::k_DXT5A, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_CTX1, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM },
|
{TextureFormat::k_CTX1, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM},
|
||||||
{ TextureFormat::k_DXT3A_AS_1_1_1_1, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::k_DXT3A_AS_1_1_1_1, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::kUnknown, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::kUnknown, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
{ TextureFormat::kUnknown, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
{TextureFormat::kUnknown, GL_INVALID_ENUM, GL_INVALID_ENUM,
|
||||||
GL_INVALID_ENUM },
|
GL_INVALID_ENUM},
|
||||||
};
|
};
|
||||||
|
|
||||||
TextureCache::TextureCache() : memory_(nullptr), scratch_buffer_(nullptr) {
|
TextureCache::TextureCache() : memory_(nullptr), scratch_buffer_(nullptr) {
|
||||||
|
@ -526,11 +526,24 @@ TextureCache::TextureEntry* TextureCache::LookupAddress(uint32_t guest_address,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint TextureCache::CopyReadBufferTexture(uint32_t guest_address, uint32_t x,
|
GLuint TextureCache::CopyTexture(Blitter* blitter, uint32_t guest_address,
|
||||||
uint32_t y, uint32_t width,
|
uint32_t x, uint32_t y, uint32_t width,
|
||||||
uint32_t height,
|
uint32_t height, TextureFormat format,
|
||||||
TextureFormat format,
|
bool swap_channels, GLuint src_texture) {
|
||||||
bool swap_channels) {
|
return ConvertTexture(blitter, guest_address, x, y, width, height, format,
|
||||||
|
swap_channels, src_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint TextureCache::ConvertTexture(Blitter* blitter, uint32_t guest_address,
|
||||||
|
uint32_t x, uint32_t y, uint32_t width,
|
||||||
|
uint32_t height, TextureFormat format,
|
||||||
|
bool swap_channels, GLuint src_texture) {
|
||||||
|
const auto& config = texture_configs[uint32_t(format)];
|
||||||
|
if (config.format == GL_INVALID_ENUM) {
|
||||||
|
assert_always("Unhandled destination texture format");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// See if we have used a texture at this address before. If we have, we can
|
// See if we have used a texture at this address before. If we have, we can
|
||||||
// reuse it.
|
// reuse it.
|
||||||
// TODO(benvanik): better lookup matching format/etc?
|
// TODO(benvanik): better lookup matching format/etc?
|
||||||
|
@ -538,8 +551,14 @@ GLuint TextureCache::CopyReadBufferTexture(uint32_t guest_address, uint32_t x,
|
||||||
if (texture_entry) {
|
if (texture_entry) {
|
||||||
// Have existing texture.
|
// Have existing texture.
|
||||||
assert_false(texture_entry->pending_invalidation);
|
assert_false(texture_entry->pending_invalidation);
|
||||||
glCopyTextureSubImage2D(texture_entry->handle, 0, 0, 0, x, y, width,
|
if (config.format == GL_DEPTH_STENCIL) {
|
||||||
height);
|
blitter->CopyDepthTexture(src_texture, x, y, width, height,
|
||||||
|
texture_entry->handle, 0, 0, width, height);
|
||||||
|
} else {
|
||||||
|
blitter->CopyColorTexture2D(src_texture, x, y, width, height,
|
||||||
|
texture_entry->handle, 0, 0, width, height,
|
||||||
|
GL_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
// HACK: remove texture from write watch list so readback won't kill us.
|
// HACK: remove texture from write watch list so readback won't kill us.
|
||||||
if (texture_entry->write_watch_handle) {
|
if (texture_entry->write_watch_handle) {
|
||||||
|
@ -557,17 +576,18 @@ GLuint TextureCache::CopyReadBufferTexture(uint32_t guest_address, uint32_t x,
|
||||||
if (entry->guest_address == guest_address && entry->width == width &&
|
if (entry->guest_address == guest_address && entry->width == width &&
|
||||||
entry->height == height && entry->format == format) {
|
entry->height == height && entry->format == format) {
|
||||||
// Found an existing entry - just reupload.
|
// Found an existing entry - just reupload.
|
||||||
glCopyTextureSubImage2D(entry->handle, 0, 0, 0, x, y, width, height);
|
if (config.format == GL_DEPTH_STENCIL) {
|
||||||
|
blitter->CopyDepthTexture(src_texture, x, y, width, height,
|
||||||
|
entry->handle, 0, 0, width, height);
|
||||||
|
} else {
|
||||||
|
blitter->CopyColorTexture2D(src_texture, x, y, width, height,
|
||||||
|
entry->handle, 0, 0, width, height,
|
||||||
|
GL_LINEAR);
|
||||||
|
}
|
||||||
return entry->handle;
|
return entry->handle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& config = texture_configs[uint32_t(format)];
|
|
||||||
if (config.format == GL_INVALID_ENUM) {
|
|
||||||
assert_always("Unhandled destination texture format");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Need to create a new texture.
|
// Need to create a new texture.
|
||||||
// As we don't know anything about this texture, we'll add it to the
|
// As we don't know anything about this texture, we'll add it to the
|
||||||
// pending readbuffer list. If nobody claims it after a certain amount
|
// pending readbuffer list. If nobody claims it after a certain amount
|
||||||
|
@ -582,7 +602,13 @@ GLuint TextureCache::CopyReadBufferTexture(uint32_t guest_address, uint32_t x,
|
||||||
glTextureParameteri(entry->handle, GL_TEXTURE_BASE_LEVEL, 0);
|
glTextureParameteri(entry->handle, GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
glTextureParameteri(entry->handle, GL_TEXTURE_MAX_LEVEL, 1);
|
glTextureParameteri(entry->handle, GL_TEXTURE_MAX_LEVEL, 1);
|
||||||
glTextureStorage2D(entry->handle, 1, config.internal_format, width, height);
|
glTextureStorage2D(entry->handle, 1, config.internal_format, width, height);
|
||||||
glCopyTextureSubImage2D(entry->handle, 0, 0, 0, x, y, width, height);
|
if (config.format == GL_DEPTH_STENCIL) {
|
||||||
|
blitter->CopyDepthTexture(src_texture, x, y, width, height, entry->handle,
|
||||||
|
0, 0, width, height);
|
||||||
|
} else {
|
||||||
|
blitter->CopyColorTexture2D(src_texture, x, y, width, height, entry->handle,
|
||||||
|
0, 0, width, height, GL_LINEAR);
|
||||||
|
}
|
||||||
|
|
||||||
GLuint handle = entry->handle;
|
GLuint handle = entry->handle;
|
||||||
read_buffer_textures_.push_back(entry.release());
|
read_buffer_textures_.push_back(entry.release());
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "xenia/gpu/gl4/blitter.h"
|
||||||
#include "xenia/gpu/gl4/circular_buffer.h"
|
#include "xenia/gpu/gl4/circular_buffer.h"
|
||||||
#include "xenia/gpu/gl4/gl_context.h"
|
#include "xenia/gpu/gl4/gl_context.h"
|
||||||
#include "xenia/gpu/sampler_info.h"
|
#include "xenia/gpu/sampler_info.h"
|
||||||
|
@ -57,9 +58,15 @@ class TextureCache {
|
||||||
|
|
||||||
TextureEntryView* Demand(const TextureInfo& texture_info,
|
TextureEntryView* Demand(const TextureInfo& texture_info,
|
||||||
const SamplerInfo& sampler_info);
|
const SamplerInfo& sampler_info);
|
||||||
GLuint CopyReadBufferTexture(uint32_t guest_address, uint32_t x, uint32_t y,
|
|
||||||
uint32_t width, uint32_t height,
|
GLuint CopyTexture(Blitter* blitter, uint32_t guest_address, uint32_t x,
|
||||||
TextureFormat format, bool swap_channels);
|
uint32_t y, uint32_t width, uint32_t height,
|
||||||
|
TextureFormat format, bool swap_channels,
|
||||||
|
GLuint src_texture);
|
||||||
|
GLuint ConvertTexture(Blitter* blitter, uint32_t guest_address, uint32_t x,
|
||||||
|
uint32_t y, uint32_t width, uint32_t height,
|
||||||
|
TextureFormat format, bool swap_channels,
|
||||||
|
GLuint src_texture);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ReadBufferTexture {
|
struct ReadBufferTexture {
|
||||||
|
|
Loading…
Reference in New Issue