render/gles2: implement wlr_renderer_bind_buffer
This commit is contained in:
		
							parent
							
								
									c88c54fb38
								
							
						
					
					
						commit
						6136fe87d1
					
				|  | @ -72,9 +72,24 @@ struct wlr_gles2_renderer { | ||||||
| 		struct wlr_gles2_tex_shader tex_ext; | 		struct wlr_gles2_tex_shader tex_ext; | ||||||
| 	} shaders; | 	} shaders; | ||||||
| 
 | 
 | ||||||
|  | 	struct wl_list buffers; // wlr_gles2_buffer.link
 | ||||||
|  | 
 | ||||||
|  | 	struct wlr_gles2_buffer *current_buffer; | ||||||
| 	uint32_t viewport_width, viewport_height; | 	uint32_t viewport_width, viewport_height; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | struct wlr_gles2_buffer { | ||||||
|  | 	struct wlr_buffer *buffer; | ||||||
|  | 	struct wlr_gles2_renderer *renderer; | ||||||
|  | 	struct wl_list link; // wlr_gles2_renderer.buffers
 | ||||||
|  | 
 | ||||||
|  | 	EGLImageKHR image; | ||||||
|  | 	GLuint rbo; | ||||||
|  | 	GLuint fbo; | ||||||
|  | 
 | ||||||
|  | 	struct wl_listener buffer_destroy; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| struct wlr_gles2_texture { | struct wlr_gles2_texture { | ||||||
| 	struct wlr_texture wlr_texture; | 	struct wlr_texture wlr_texture; | ||||||
| 	struct wlr_gles2_renderer *renderer; | 	struct wlr_gles2_renderer *renderer; | ||||||
|  |  | ||||||
|  | @ -36,6 +36,139 @@ static struct wlr_gles2_renderer *gles2_get_renderer_in_context( | ||||||
| 	return renderer; | 	return renderer; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static void destroy_buffer(struct wlr_gles2_buffer *buffer) { | ||||||
|  | 	wl_list_remove(&buffer->link); | ||||||
|  | 	wl_list_remove(&buffer->buffer_destroy.link); | ||||||
|  | 
 | ||||||
|  | 	wlr_egl_make_current(buffer->renderer->egl, EGL_NO_SURFACE, NULL); | ||||||
|  | 
 | ||||||
|  | 	push_gles2_debug(buffer->renderer); | ||||||
|  | 
 | ||||||
|  | 	glDeleteFramebuffers(1, &buffer->fbo); | ||||||
|  | 	glDeleteRenderbuffers(1, &buffer->rbo); | ||||||
|  | 
 | ||||||
|  | 	pop_gles2_debug(buffer->renderer); | ||||||
|  | 
 | ||||||
|  | 	wlr_egl_destroy_image(buffer->renderer->egl, buffer->image); | ||||||
|  | 	wlr_egl_unset_current(buffer->renderer->egl); | ||||||
|  | 	free(buffer); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct wlr_gles2_buffer *get_buffer(struct wlr_gles2_renderer *renderer, | ||||||
|  | 		struct wlr_buffer *wlr_buffer) { | ||||||
|  | 	struct wlr_gles2_buffer *buffer; | ||||||
|  | 	wl_list_for_each(buffer, &renderer->buffers, link) { | ||||||
|  | 		if (buffer->buffer == wlr_buffer) { | ||||||
|  | 			return buffer; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void handle_buffer_destroy(struct wl_listener *listener, void *data) { | ||||||
|  | 	struct wlr_gles2_buffer *buffer = | ||||||
|  | 		wl_container_of(listener, buffer, buffer_destroy); | ||||||
|  | 	destroy_buffer(buffer); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static struct wlr_gles2_buffer *create_buffer(struct wlr_gles2_renderer *renderer, | ||||||
|  | 		struct wlr_buffer *wlr_buffer) { | ||||||
|  | 	struct wlr_gles2_buffer *buffer = calloc(1, sizeof(*buffer)); | ||||||
|  | 	if (buffer == NULL) { | ||||||
|  | 		wlr_log_errno(WLR_ERROR, "Allocation failed"); | ||||||
|  | 		return NULL; | ||||||
|  | 	} | ||||||
|  | 	buffer->buffer = wlr_buffer; | ||||||
|  | 	buffer->renderer = renderer; | ||||||
|  | 
 | ||||||
|  | 	struct wlr_dmabuf_attributes dmabuf = {0}; | ||||||
|  | 	if (!wlr_buffer_get_dmabuf(wlr_buffer, &dmabuf)) { | ||||||
|  | 		goto error_buffer; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	bool external_only; | ||||||
|  | 	buffer->image = wlr_egl_create_image_from_dmabuf(renderer->egl, | ||||||
|  | 		&dmabuf, &external_only); | ||||||
|  | 	if (buffer->image == EGL_NO_IMAGE_KHR) { | ||||||
|  | 		goto error_buffer; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	push_gles2_debug(renderer); | ||||||
|  | 
 | ||||||
|  | 	glGenRenderbuffers(1, &buffer->rbo); | ||||||
|  | 	glBindRenderbuffer(GL_RENDERBUFFER, buffer->rbo); | ||||||
|  | 	renderer->procs.glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, | ||||||
|  | 		buffer->image); | ||||||
|  | 	glBindRenderbuffer(GL_RENDERBUFFER, 0); | ||||||
|  | 
 | ||||||
|  | 	glGenFramebuffers(1, &buffer->fbo); | ||||||
|  | 	glBindFramebuffer(GL_FRAMEBUFFER, buffer->fbo); | ||||||
|  | 	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, | ||||||
|  | 		GL_RENDERBUFFER, buffer->rbo); | ||||||
|  | 	GLenum fb_status = glCheckFramebufferStatus(GL_FRAMEBUFFER); | ||||||
|  | 	glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||||||
|  | 
 | ||||||
|  | 	pop_gles2_debug(renderer); | ||||||
|  | 
 | ||||||
|  | 	if (fb_status != GL_FRAMEBUFFER_COMPLETE) { | ||||||
|  | 		wlr_log(WLR_ERROR, "Failed to create FBO"); | ||||||
|  | 		goto error_image; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	buffer->buffer_destroy.notify = handle_buffer_destroy; | ||||||
|  | 	wl_signal_add(&wlr_buffer->events.destroy, &buffer->buffer_destroy); | ||||||
|  | 
 | ||||||
|  | 	wl_list_insert(&renderer->buffers, &buffer->link); | ||||||
|  | 
 | ||||||
|  | 	wlr_log(WLR_DEBUG, "Created GL FBO for buffer %dx%d", | ||||||
|  | 		wlr_buffer->width, wlr_buffer->height); | ||||||
|  | 
 | ||||||
|  | 	return buffer; | ||||||
|  | 
 | ||||||
|  | error_image: | ||||||
|  | 	wlr_egl_destroy_image(renderer->egl, buffer->image); | ||||||
|  | error_buffer: | ||||||
|  | 	free(buffer); | ||||||
|  | 	return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static bool gles2_bind_buffer(struct wlr_renderer *wlr_renderer, | ||||||
|  | 		struct wlr_buffer *wlr_buffer) { | ||||||
|  | 	struct wlr_gles2_renderer *renderer = | ||||||
|  | 		gles2_get_renderer_in_context(wlr_renderer); | ||||||
|  | 
 | ||||||
|  | 	if (renderer->current_buffer != NULL) { | ||||||
|  | 		push_gles2_debug(renderer); | ||||||
|  | 		glFlush(); | ||||||
|  | 		glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||||||
|  | 		pop_gles2_debug(renderer); | ||||||
|  | 
 | ||||||
|  | 		wlr_buffer_unlock(renderer->current_buffer->buffer); | ||||||
|  | 		renderer->current_buffer = NULL; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if (wlr_buffer == NULL) { | ||||||
|  | 		return true; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	struct wlr_gles2_buffer *buffer = get_buffer(renderer, wlr_buffer); | ||||||
|  | 	if (buffer == NULL) { | ||||||
|  | 		buffer = create_buffer(renderer, wlr_buffer); | ||||||
|  | 	} | ||||||
|  | 	if (buffer == NULL) { | ||||||
|  | 		return false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	wlr_buffer_lock(wlr_buffer); | ||||||
|  | 	renderer->current_buffer = buffer; | ||||||
|  | 
 | ||||||
|  | 	push_gles2_debug(renderer); | ||||||
|  | 	glBindFramebuffer(GL_FRAMEBUFFER, renderer->current_buffer->fbo); | ||||||
|  | 	pop_gles2_debug(renderer); | ||||||
|  | 
 | ||||||
|  | 	return true; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void gles2_begin(struct wlr_renderer *wlr_renderer, uint32_t width, | static void gles2_begin(struct wlr_renderer *wlr_renderer, uint32_t width, | ||||||
| 		uint32_t height) { | 		uint32_t height) { | ||||||
| 	struct wlr_gles2_renderer *renderer = | 	struct wlr_gles2_renderer *renderer = | ||||||
|  | @ -477,6 +610,11 @@ static void gles2_destroy(struct wlr_renderer *wlr_renderer) { | ||||||
| 
 | 
 | ||||||
| 	wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL); | 	wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL); | ||||||
| 
 | 
 | ||||||
|  | 	struct wlr_gles2_buffer *buffer, *buffer_tmp; | ||||||
|  | 	wl_list_for_each_safe(buffer, buffer_tmp, &renderer->buffers, link) { | ||||||
|  | 		destroy_buffer(buffer); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	push_gles2_debug(renderer); | 	push_gles2_debug(renderer); | ||||||
| 	glDeleteProgram(renderer->shaders.quad.program); | 	glDeleteProgram(renderer->shaders.quad.program); | ||||||
| 	glDeleteProgram(renderer->shaders.ellipse.program); | 	glDeleteProgram(renderer->shaders.ellipse.program); | ||||||
|  | @ -497,6 +635,7 @@ static void gles2_destroy(struct wlr_renderer *wlr_renderer) { | ||||||
| 
 | 
 | ||||||
| static const struct wlr_renderer_impl renderer_impl = { | static const struct wlr_renderer_impl renderer_impl = { | ||||||
| 	.destroy = gles2_destroy, | 	.destroy = gles2_destroy, | ||||||
|  | 	.bind_buffer = gles2_bind_buffer, | ||||||
| 	.begin = gles2_begin, | 	.begin = gles2_begin, | ||||||
| 	.end = gles2_end, | 	.end = gles2_end, | ||||||
| 	.clear = gles2_clear, | 	.clear = gles2_clear, | ||||||
|  | @ -668,6 +807,8 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { | ||||||
| 	} | 	} | ||||||
| 	wlr_renderer_init(&renderer->wlr_renderer, &renderer_impl); | 	wlr_renderer_init(&renderer->wlr_renderer, &renderer_impl); | ||||||
| 
 | 
 | ||||||
|  | 	wl_list_init(&renderer->buffers); | ||||||
|  | 
 | ||||||
| 	renderer->egl = egl; | 	renderer->egl = egl; | ||||||
| 	renderer->exts_str = exts_str; | 	renderer->exts_str = exts_str; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue