diff --git a/include/render.h b/include/render.h index caf3117..022c13d 100644 --- a/include/render.h +++ b/include/render.h @@ -32,7 +32,6 @@ enum renderer_input_type { struct renderer_fbo { GLuint rbo; GLuint fbo; - GLuint tex; }; struct renderer { @@ -50,12 +49,9 @@ struct renderer { GLuint tex[2]; int tex_index; - GLenum tex_target; - struct { GLuint program; GLint u_tex0; - GLint u_tex1; GLint u_proj; } frame_shader; @@ -63,7 +59,6 @@ struct renderer { GLuint program; GLint u_tex0; GLint u_tex1; - GLint u_proj; } damage_shader; }; @@ -71,19 +66,17 @@ int renderer_init(struct renderer* self, const struct output* output, enum renderer_input_type input_type); void renderer_destroy(struct renderer* self); -int renderer_import_dmabuf_frame(struct renderer* self, GLuint tex, - struct dmabuf_frame* frame); -int renderer_import_framebuffer(struct renderer* self, GLuint tex, - const void* addr, uint32_t format, - uint32_t width, uint32_t height, - uint32_t stride); +int render_dmabuf(struct renderer* self, struct dmabuf_frame* frame); +int render_framebuffer(struct renderer* self, const void* addr, uint32_t format, + uint32_t width, uint32_t height, uint32_t stride); /* Copy a horizontal stripe from the GL frame into a pixel buffer */ -void render_copy_pixels(struct renderer* self, void* dst, uint32_t y, - uint32_t height); +void renderer_read_frame(struct renderer* self, void* dst, uint32_t y, + uint32_t height); -GLuint renderer_next_tex(struct renderer* self); -GLuint renderer_last_tex(const struct renderer* self); +void renderer_read_damage(struct renderer* self, void* dst, uint32_t y, + uint32_t height); + +void renderer_swap_textures(struct renderer* self); -void render(struct renderer* self); void render_damage(struct renderer* self); diff --git a/shaders/texture-damage-fragment.glsl b/shaders/damage-fragment.glsl similarity index 100% rename from shaders/texture-damage-fragment.glsl rename to shaders/damage-fragment.glsl diff --git a/shaders/damage-vertex.glsl b/shaders/damage-vertex.glsl new file mode 100644 index 0000000..020f11a --- /dev/null +++ b/shaders/damage-vertex.glsl @@ -0,0 +1,12 @@ +uniform mat2 u_proj; + +attribute vec2 pos; +attribute vec2 texture; + +varying vec2 v_texture; + +void main() +{ + v_texture = texture; + gl_Position = vec4(u_proj * pos, 0, 1); +} diff --git a/shaders/dmabuf-damage-fragment.glsl b/shaders/dmabuf-damage-fragment.glsl deleted file mode 100644 index ebaf001..0000000 --- a/shaders/dmabuf-damage-fragment.glsl +++ /dev/null @@ -1,13 +0,0 @@ -#extension GL_OES_EGL_image_external: require - -precision mediump float; - -uniform samplerExternalOES u_tex0; - -varying vec2 v_texture; - -void main() -{ - float r = float(texture2D(u_tex0, v_texture).rgb != texture2D(u_tex1, v_texture).rgb); - gl_FragColor = vec4(r); -} diff --git a/src/main.c b/src/main.c index 289c6ec..38eff39 100644 --- a/src/main.c +++ b/src/main.c @@ -516,10 +516,8 @@ void wayvnc_process_frame(struct wayvnc* self) struct nvnc_fb* fb = nvnc_fb_new(fb_width, fb_height, format); void* addr = nvnc_fb_get_addr(fb); - GLuint tex = renderer_next_tex(&self->renderer); - renderer_import_dmabuf_frame(&self->renderer, tex, frame); - render(&self->renderer); - render_copy_pixels(&self->renderer, addr, 0, fb_height); + render_dmabuf(&self->renderer, frame); + renderer_read_frame(&self->renderer, addr, 0, fb_height); wayvnc_update_vnc(self, fb); } @@ -542,11 +540,9 @@ void wayvnc_process_screen(struct wayvnc* self) struct nvnc_fb* fb = nvnc_fb_new(fb_width, fb_height, renderer_format); void* addr = nvnc_fb_get_addr(fb); - GLuint tex = renderer_next_tex(&self->renderer); - renderer_import_framebuffer(&self->renderer, tex, pixels, frame_format, - width, height, stride); - render(&self->renderer); - render_copy_pixels(&self->renderer, addr, 0, fb_height); + render_framebuffer(&self->renderer, pixels, frame_format, width, height, + stride); + renderer_read_frame(&self->renderer, addr, 0, fb_height); wayvnc_update_vnc(self, fb); } diff --git a/src/render.c b/src/render.c index edfb4a0..9e7fcdb 100644 --- a/src/render.c +++ b/src/render.c @@ -348,27 +348,6 @@ fragment_failure: return rc; } -GLuint renderer_next_tex(struct renderer* self) -{ - GLuint tex = self->tex[self->tex_index]; - self->tex_index = (self->tex_index + 1) % ARRAY_LEN(self->tex); - return tex; -} - -GLuint renderer_current_tex(const struct renderer* self) -{ - size_t len = ARRAY_LEN(self->tex); - size_t index = (len + self->tex_index - 1) % len; - return self->tex[index]; -} - -GLuint renderer_last_tex(const struct renderer* self) -{ - size_t len = ARRAY_LEN(self->tex); - size_t index = (len + self->tex_index - 2) % len; - return self->tex[index]; -} - void gl_clear(void) { glClearColor(0.0, 0.0, 0.0, 1.0); @@ -407,24 +386,33 @@ void gl_draw(void) glDisableVertexAttribArray(1); } -void render(struct renderer* self) +void renderer_swap_textures(struct renderer* self) +{ + self->tex_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) { glBindFramebuffer(GL_FRAMEBUFFER, self->frame_fbo.fbo); - glActiveTexture(GL_TEXTURE0); - glBindTexture(self->tex_target, renderer_current_tex(self)); - glActiveTexture(GL_TEXTURE1); - glBindTexture(self->tex_target, renderer_last_tex(self)); + renderer_swap_textures(self); glUseProgram(self->frame_shader.program); glUniform1i(self->frame_shader.u_tex0, 0); - glUniform1i(self->frame_shader.u_tex1, 1); const float* proj = transforms[self->output->transform]; glUniformMatrix2fv(self->frame_shader.u_proj, 1, GL_FALSE, proj); gl_draw(); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); } void render_damage(struct renderer* self) @@ -432,28 +420,24 @@ void render_damage(struct renderer* self) glBindFramebuffer(GL_FRAMEBUFFER, self->damage_fbo.fbo); glActiveTexture(GL_TEXTURE0); - glBindTexture(self->tex_target, renderer_current_tex(self)); + glBindTexture(GL_TEXTURE_2D, self->tex[self->tex_index]); glActiveTexture(GL_TEXTURE1); - glBindTexture(self->tex_target, renderer_last_tex(self)); + glBindTexture(GL_TEXTURE_2D, self->tex[!self->tex_index]); glUseProgram(self->damage_shader.program); glUniform1i(self->damage_shader.u_tex0, 0); glUniform1i(self->damage_shader.u_tex1, 1); - const float* proj = transforms[self->output->transform]; - glUniformMatrix2fv(self->damage_shader.u_proj, 1, GL_FALSE, proj); - gl_draw(); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); } void destroy_fbo(struct renderer_fbo* fbo) { glDeleteFramebuffers(1, &fbo->fbo); glDeleteRenderbuffers(1, &fbo->rbo); - - if (fbo->tex) - glDeleteTextures(1, &fbo->tex); } int create_fbo(struct renderer_fbo* dst, GLint format, uint32_t width, @@ -480,13 +464,12 @@ int create_fbo(struct renderer_fbo* dst, GLint format, uint32_t width, dst->fbo = fbo; dst->rbo = rbo; - dst->tex = 0; return 0; } -int create_textured_fbo(struct renderer_fbo* dst, GLint format, uint32_t width, - uint32_t height) +int create_textured_fbo(struct renderer_fbo* dst, uint32_t width, + uint32_t height, GLuint tex) { GLuint rbo = 0; glGenRenderbuffers(1, &rbo); @@ -495,15 +478,6 @@ int create_textured_fbo(struct renderer_fbo* dst, GLint format, uint32_t width, height); glBindRenderbuffer(GL_RENDERBUFFER, 0); - 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); - GLuint fbo = 0; glGenFramebuffers(1, &fbo); glBindFramebuffer(GL_FRAMEBUFFER, fbo); @@ -522,11 +496,23 @@ int create_textured_fbo(struct renderer_fbo* dst, GLint format, uint32_t width, dst->fbo = fbo; dst->rbo = rbo; - dst->tex = tex; 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) { glDeleteProgram(self->frame_shader.program); @@ -592,13 +578,14 @@ int renderer_init(struct renderer* self, const struct output* output, if (gl_load_late_extensions() < 0) goto late_extension_failure; - glGenTextures(ARRAY_LEN(self->tex), self->tex); - uint32_t tf_width = output_get_transformed_width(output); uint32_t tf_height = output_get_transformed_height(output); - if (create_textured_fbo(&self->frame_fbo, GL_RGBA, tf_width, - tf_height) < 0) + self->tex[0] = create_texture_attachment(GL_RGBA, tf_width, tf_height); + self->tex[1] = create_texture_attachment(GL_RGBA, tf_width, tf_height); + + if (create_textured_fbo(&self->frame_fbo, tf_width, tf_height, + self->tex[0]) < 0) goto frame_fbo_failure; if (create_fbo(&self->damage_fbo, GL_R8_EXT, tf_width, tf_height) < 0) @@ -608,37 +595,26 @@ int renderer_init(struct renderer* self, const struct output* output, switch (input_type) { case RENDERER_INPUT_DMABUF: - self->tex_target = GL_TEXTURE_EXTERNAL_OES; - if (gl_compile_shader_program(&self->frame_shader.program, "dmabuf-vertex.glsl", "dmabuf-fragment.glsl") < 0) goto frame_shader_failure; - - if (gl_compile_shader_program(&self->damage_shader.program, - "dmabuf-vertex.glsl", - "dmabuf-damage-fragment.glsl") < 0) - goto damage_shader_failure; break; case RENDERER_INPUT_FB: - self->tex_target = GL_TEXTURE_2D; - if (gl_compile_shader_program(&self->frame_shader.program, "texture-vertex.glsl", "texture-fragment.glsl") < 0) goto frame_shader_failure; - - if (gl_compile_shader_program(&self->damage_shader.program, - "texture-vertex.glsl", - "texture-damage-fragment.glsl") < 0) - goto damage_shader_failure; break; } + if (gl_compile_shader_program(&self->damage_shader.program, + "damage-vertex.glsl", + "damage-fragment.glsl") < 0) + goto damage_shader_failure; + self->frame_shader.u_tex0 = glGetUniformLocation(self->frame_shader.program, "u_tex0"); - self->frame_shader.u_tex1 = - glGetUniformLocation(self->frame_shader.program, "u_tex1"); self->frame_shader.u_proj = glGetUniformLocation(self->frame_shader.program, "u_proj"); @@ -646,8 +622,6 @@ int renderer_init(struct renderer* self, const struct output* output, glGetUniformLocation(self->damage_shader.program, "u_tex0"); self->damage_shader.u_tex1 = glGetUniformLocation(self->damage_shader.program, "u_tex1"); - self->damage_shader.u_proj = - glGetUniformLocation(self->damage_shader.program, "u_proj"); self->output = output; glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &self->read_format); @@ -703,8 +677,7 @@ static void dmabuf_attr_append_planes(EGLint* dst, int* i, #undef APPEND_PLANE_ATTR } -int renderer_import_dmabuf_frame(struct renderer* self, GLuint tex, - struct dmabuf_frame* frame) +int render_dmabuf(struct renderer* self, struct dmabuf_frame* frame) { int index = 0; EGLint attr[6 + 10 * 4 + 1]; @@ -724,22 +697,29 @@ int renderer_import_dmabuf_frame(struct renderer* self, GLuint tex, if (!image) return -1; + GLuint tex = 0; + glGenTextures(1, &tex); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex); glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, image); eglDestroyImageKHR(self->display, image); + render_frame(self); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); + glDeleteTextures(1, &tex); return 0; } -int renderer_import_framebuffer(struct renderer* self, GLuint tex, - const void* addr, uint32_t format, - uint32_t width, uint32_t height, - uint32_t stride) +int render_framebuffer(struct renderer* self, const void* addr, uint32_t format, + uint32_t width, uint32_t height, uint32_t stride) { + GLuint tex = 0; + glGenTextures(1, &tex); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, tex); @@ -753,13 +733,16 @@ int renderer_import_framebuffer(struct renderer* self, GLuint tex, glGenerateMipmap(GL_TEXTURE_2D); glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); + render_frame(self); + glBindTexture(GL_TEXTURE_2D, 0); + glDeleteTextures(1, &tex); return 0; } -void render_copy_pixels(struct renderer* self, void* dst, uint32_t y, - uint32_t height) +void renderer_read_pixels(struct renderer* self, void* dst, uint32_t y, + uint32_t height) { assert(y + height <= output_get_transformed_height(self->output)); @@ -771,3 +754,19 @@ void render_copy_pixels(struct renderer* self, void* dst, uint32_t y, glReadPixels(0, y, width, height, read_format, read_type, dst); } + +void renderer_read_frame(struct renderer* self, void* dst, uint32_t y, + uint32_t height) +{ + glBindFramebuffer(GL_FRAMEBUFFER, self->frame_fbo.fbo); + renderer_read_pixels(self, dst, y, height); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +} + +void renderer_read_damage(struct renderer* self, void* dst, uint32_t y, + uint32_t height) +{ + glBindFramebuffer(GL_FRAMEBUFFER, self->damage_fbo.fbo); + renderer_read_pixels(self, dst, y, height); + glBindFramebuffer(GL_FRAMEBUFFER, 0); +}