renderer: Swap FPOs rather than textures

shader-damage-experiments
Andri Yngvason 2020-03-27 19:33:42 +00:00
parent f0fa12425b
commit b0a6b6bd2a
2 changed files with 37 additions and 53 deletions

View File

@ -32,6 +32,7 @@ enum renderer_input_type {
struct renderer_fbo { struct renderer_fbo {
GLuint rbo; GLuint rbo;
GLuint fbo; GLuint fbo;
GLuint tex;
}; };
struct renderer { struct renderer {
@ -43,11 +44,10 @@ struct renderer {
GLint read_format; GLint read_format;
GLint read_type; GLint read_type;
struct renderer_fbo frame_fbo; struct renderer_fbo frame_fbo[2];
struct renderer_fbo damage_fbo; int frame_index;
GLuint tex[2]; struct renderer_fbo damage_fbo;
int tex_index;
struct { struct {
GLuint program; GLuint program;

View File

@ -386,22 +386,16 @@ void gl_draw(void)
glDisableVertexAttribArray(1); glDisableVertexAttribArray(1);
} }
void renderer_swap_textures(struct renderer* self) void renderer_swap(struct renderer* self)
{ {
self->tex_index ^= 1; self->frame_index ^= 1;
GLuint tex = self->tex[self->tex_index];
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, tex, 0);
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
} }
void render_frame(struct renderer* self) void render_frame(struct renderer* self)
{ {
glBindFramebuffer(GL_FRAMEBUFFER, self->frame_fbo.fbo); renderer_swap(self);
renderer_swap_textures(self); glBindFramebuffer(GL_FRAMEBUFFER, self->frame_fbo[self->frame_index].fbo);
glUseProgram(self->frame_shader.program); glUseProgram(self->frame_shader.program);
@ -420,9 +414,9 @@ void render_damage(struct renderer* self)
glBindFramebuffer(GL_FRAMEBUFFER, self->damage_fbo.fbo); glBindFramebuffer(GL_FRAMEBUFFER, self->damage_fbo.fbo);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, self->tex[self->tex_index]); glBindTexture(GL_TEXTURE_2D, self->frame_fbo[self->frame_index].tex);
glActiveTexture(GL_TEXTURE1); glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, self->tex[!self->tex_index]); glBindTexture(GL_TEXTURE_2D, self->frame_fbo[!self->frame_index].tex);
glUseProgram(self->damage_shader.program); glUseProgram(self->damage_shader.program);
@ -438,6 +432,8 @@ void destroy_fbo(struct renderer_fbo* fbo)
{ {
glDeleteFramebuffers(1, &fbo->fbo); glDeleteFramebuffers(1, &fbo->fbo);
glDeleteRenderbuffers(1, &fbo->rbo); glDeleteRenderbuffers(1, &fbo->rbo);
if (fbo->tex)
glDeleteTextures(1, &fbo->tex);
} }
int create_fbo(struct renderer_fbo* dst, GLint format, uint32_t width, int create_fbo(struct renderer_fbo* dst, GLint format, uint32_t width,
@ -464,26 +460,26 @@ int create_fbo(struct renderer_fbo* dst, GLint format, uint32_t width,
dst->fbo = fbo; dst->fbo = fbo;
dst->rbo = rbo; dst->rbo = rbo;
dst->tex = 0;
return 0; return 0;
} }
int create_textured_fbo(struct renderer_fbo* dst, uint32_t width, int create_textured_fbo(struct renderer_fbo* dst, GLint format, uint32_t width,
uint32_t height, GLuint tex) uint32_t height)
{ {
GLuint rbo = 0; GLuint tex = 0;
glGenRenderbuffers(1, &rbo); glGenTextures(1, &tex);
glBindRenderbuffer(GL_RENDERBUFFER, rbo); glBindTexture(GL_TEXTURE_2D, tex);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, width, glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format,
height); GL_UNSIGNED_BYTE, NULL);
glBindRenderbuffer(GL_RENDERBUFFER, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
GLuint fbo = 0; GLuint fbo = 0;
glGenFramebuffers(1, &fbo); glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferRenderbuffer(GL_FRAMEBUFFER,
GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER, rbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, tex, 0); GL_TEXTURE_2D, tex, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
@ -495,31 +491,19 @@ int create_textured_fbo(struct renderer_fbo* dst, uint32_t width,
} }
dst->fbo = fbo; dst->fbo = fbo;
dst->rbo = rbo; dst->rbo = 0;
dst->tex = tex;
return 0; return 0;
} }
GLuint create_texture_attachment(GLint format, uint32_t width, uint32_t height)
{
GLuint tex = 0;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format,
GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
return tex;
}
void renderer_destroy(struct renderer* self) void renderer_destroy(struct renderer* self)
{ {
glDeleteProgram(self->frame_shader.program); glDeleteProgram(self->frame_shader.program);
eglMakeCurrent(self->display, EGL_NO_SURFACE, EGL_NO_SURFACE, eglMakeCurrent(self->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT); EGL_NO_CONTEXT);
destroy_fbo(&self->frame_fbo); destroy_fbo(&self->frame_fbo[1]);
glDeleteTextures(ARRAY_LEN(self->tex), self->tex); destroy_fbo(&self->frame_fbo[0]);
eglDestroyContext(self->display, self->context); eglDestroyContext(self->display, self->context);
eglTerminate(self->display); eglTerminate(self->display);
} }
@ -581,17 +565,16 @@ int renderer_init(struct renderer* self, const struct output* output,
uint32_t tf_width = output_get_transformed_width(output); uint32_t tf_width = output_get_transformed_width(output);
uint32_t tf_height = output_get_transformed_height(output); uint32_t tf_height = output_get_transformed_height(output);
self->tex[0] = create_texture_attachment(GL_RGBA, tf_width, tf_height); if (create_textured_fbo(&self->frame_fbo[0], GL_RGBA, tf_width, tf_height) < 0)
self->tex[1] = create_texture_attachment(GL_RGBA, tf_width, tf_height); goto frame_fbo_failure_0;
if (create_textured_fbo(&self->frame_fbo, tf_width, tf_height, if (create_textured_fbo(&self->frame_fbo[1], GL_RGBA, tf_width, tf_height) < 0)
self->tex[0]) < 0) goto frame_fbo_failure_1;
goto frame_fbo_failure;
if (create_fbo(&self->damage_fbo, GL_R8_EXT, tf_width, tf_height) < 0) if (create_fbo(&self->damage_fbo, GL_R8_EXT, tf_width, tf_height) < 0)
goto damage_fbo_failure; goto damage_fbo_failure;
glBindFramebuffer(GL_FRAMEBUFFER, self->frame_fbo.fbo); glBindFramebuffer(GL_FRAMEBUFFER, self->frame_fbo[0].fbo);
switch (input_type) { switch (input_type) {
case RENDERER_INPUT_DMABUF: case RENDERER_INPUT_DMABUF:
@ -640,9 +623,10 @@ damage_shader_failure:
frame_shader_failure: frame_shader_failure:
destroy_fbo(&self->damage_fbo); destroy_fbo(&self->damage_fbo);
damage_fbo_failure: damage_fbo_failure:
destroy_fbo(&self->frame_fbo); destroy_fbo(&self->frame_fbo[1]);
frame_fbo_failure: frame_fbo_failure_1:
glDeleteTextures(ARRAY_LEN(self->tex), self->tex); destroy_fbo(&self->frame_fbo[0]);
frame_fbo_failure_0:
late_extension_failure: late_extension_failure:
make_current_failure: make_current_failure:
eglDestroyContext(self->display, self->context); eglDestroyContext(self->display, self->context);
@ -758,7 +742,7 @@ void renderer_read_pixels(struct renderer* self, void* dst, uint32_t y,
void renderer_read_frame(struct renderer* self, void* dst, uint32_t y, void renderer_read_frame(struct renderer* self, void* dst, uint32_t y,
uint32_t height) uint32_t height)
{ {
glBindFramebuffer(GL_FRAMEBUFFER, self->frame_fbo.fbo); glBindFramebuffer(GL_FRAMEBUFFER, self->frame_fbo[self->frame_index].fbo);
renderer_read_pixels(self, dst, y, height); renderer_read_pixels(self, dst, y, height);
glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindFramebuffer(GL_FRAMEBUFFER, 0);
} }