mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-10-29 05:40:12 -04:00 
			
		
		
		
	render/egl: introduce wlr_egl_unset_current
This function can be called after wlr_egl_make_current to cleanup the EGL context. This avoids having lingering EGL contexts that make things work by chance. Closes: https://github.com/swaywm/wlroots/issues/2197
This commit is contained in:
		
							parent
							
								
									781ed1ff02
								
							
						
					
					
						commit
						1edc42157b
					
				
					 8 changed files with 62 additions and 29 deletions
				
			
		|  | @ -556,14 +556,14 @@ static bool drm_connector_commit(struct wlr_output *output) { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_egl_make_current(&drm->renderer.egl, EGL_NO_SURFACE, NULL); | ||||
| 	wlr_egl_unset_current(&drm->renderer.egl); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void drm_connector_rollback(struct wlr_output *output) { | ||||
| 	struct wlr_drm_backend *drm = get_drm_backend_from_backend(output->backend); | ||||
| 	wlr_egl_make_current(&drm->renderer.egl, EGL_NO_SURFACE, NULL); | ||||
| 	wlr_egl_unset_current(&drm->renderer.egl); | ||||
| } | ||||
| 
 | ||||
| size_t drm_crtc_get_gamma_lut_size(struct wlr_drm_backend *drm, | ||||
|  |  | |||
|  | @ -35,6 +35,8 @@ static bool create_fbo(struct wlr_headless_output *output, | |||
| 	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); | ||||
| 	glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||||
| 
 | ||||
| 	wlr_egl_unset_current(output->backend->egl); | ||||
| 
 | ||||
| 	if (status != GL_FRAMEBUFFER_COMPLETE) { | ||||
| 		wlr_log(WLR_ERROR, "Failed to create FBO"); | ||||
| 		return false; | ||||
|  | @ -52,6 +54,9 @@ static void destroy_fbo(struct wlr_headless_output *output) { | |||
| 
 | ||||
| 	glDeleteFramebuffers(1, &output->fbo); | ||||
| 	glDeleteRenderbuffers(1, &output->rbo); | ||||
| 
 | ||||
| 	wlr_egl_unset_current(output->backend->egl); | ||||
| 
 | ||||
| 	output->fbo = 0; | ||||
| 	output->rbo = 0; | ||||
| } | ||||
|  | @ -125,21 +130,23 @@ static bool output_commit(struct wlr_output *wlr_output) { | |||
| 	} | ||||
| 
 | ||||
| 	if (wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { | ||||
| 		glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||||
| 		wlr_egl_unset_current(output->backend->egl); | ||||
| 
 | ||||
| 		// Nothing needs to be done for FBOs
 | ||||
| 		wlr_output_send_present(wlr_output, NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_egl_make_current(output->backend->egl, EGL_NO_SURFACE, NULL); | ||||
| 	glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void output_rollback(struct wlr_output *wlr_output) { | ||||
| 	struct wlr_headless_output *output = | ||||
| 		headless_output_from_output(wlr_output); | ||||
| 	wlr_egl_make_current(output->backend->egl, EGL_NO_SURFACE, NULL); | ||||
| 	glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||||
| 	if (wlr_output->pending.committed & WLR_OUTPUT_STATE_BUFFER) { | ||||
| 		glBindFramebuffer(GL_FRAMEBUFFER, 0); | ||||
| 		wlr_egl_unset_current(output->backend->egl); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void output_destroy(struct wlr_output *wlr_output) { | ||||
|  |  | |||
|  | @ -300,7 +300,7 @@ static bool output_commit(struct wlr_output *wlr_output) { | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_egl_make_current(&output->backend->egl, EGL_NO_SURFACE, NULL); | ||||
| 	wlr_egl_unset_current(&output->backend->egl); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
|  | @ -308,7 +308,7 @@ static bool output_commit(struct wlr_output *wlr_output) { | |||
| static void output_rollback(struct wlr_output *wlr_output) { | ||||
| 	struct wlr_wl_output *output = | ||||
| 		get_wl_output_from_output(wlr_output); | ||||
| 	wlr_egl_make_current(&output->backend->egl, EGL_NO_SURFACE, NULL); | ||||
| 	wlr_egl_unset_current(&output->backend->egl); | ||||
| } | ||||
| 
 | ||||
| static bool output_set_cursor(struct wlr_output *wlr_output, | ||||
|  | @ -377,6 +377,7 @@ static bool output_set_cursor(struct wlr_output *wlr_output, | |||
| 
 | ||||
| 		wlr_egl_swap_buffers(&backend->egl, egl_surface, NULL); | ||||
| 		wlr_egl_destroy_surface(&backend->egl, egl_surface); | ||||
| 		wlr_egl_unset_current(&backend->egl); | ||||
| 	} else { | ||||
| 		wl_surface_attach(surface, NULL, 0, 0); | ||||
| 		wl_surface_commit(surface); | ||||
|  | @ -583,6 +584,7 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *wlr_backend) { | |||
| 			NULL)) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 	wlr_egl_unset_current(&output->backend->egl); | ||||
| 
 | ||||
| 	wl_list_insert(&backend->outputs, &output->link); | ||||
| 	wlr_output_update_enabled(wlr_output, true); | ||||
|  |  | |||
|  | @ -157,14 +157,14 @@ static bool output_commit(struct wlr_output *wlr_output) { | |||
| 		wlr_output_send_present(wlr_output, NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_egl_make_current(&x11->egl, EGL_NO_SURFACE, NULL); | ||||
| 	wlr_egl_unset_current(&x11->egl); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void output_rollback(struct wlr_output *wlr_output) { | ||||
| 	struct wlr_x11_output *output = get_x11_output_from_output(wlr_output); | ||||
| 	wlr_egl_make_current(&output->x11->egl, EGL_NO_SURFACE, NULL); | ||||
| 	wlr_egl_unset_current(&output->x11->egl); | ||||
| } | ||||
| 
 | ||||
| static const struct wlr_output_impl output_impl = { | ||||
|  |  | |||
|  | @ -122,9 +122,18 @@ bool wlr_egl_export_image_to_dmabuf(struct wlr_egl *egl, EGLImageKHR image, | |||
|  */ | ||||
| bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImageKHR image); | ||||
| 
 | ||||
| /**
 | ||||
|  * Make the EGL context current. The provided surface will be made current | ||||
|  * unless EGL_NO_SURFACE. | ||||
|  * | ||||
|  * Callers are expected to clear the current context when they are done by | ||||
|  * calling wlr_egl_unset_current. | ||||
|  */ | ||||
| bool wlr_egl_make_current(struct wlr_egl *egl, EGLSurface surface, | ||||
| 	int *buffer_age); | ||||
| 
 | ||||
| bool wlr_egl_unset_current(struct wlr_egl *egl); | ||||
| 
 | ||||
| bool wlr_egl_is_current(struct wlr_egl *egl); | ||||
| 
 | ||||
| bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface, | ||||
|  |  | |||
							
								
								
									
										11
									
								
								render/egl.c
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								render/egl.c
									
										
									
									
									
								
							|  | @ -387,6 +387,15 @@ bool wlr_egl_make_current(struct wlr_egl *egl, EGLSurface surface, | |||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool wlr_egl_unset_current(struct wlr_egl *egl) { | ||||
| 	if (!eglMakeCurrent(egl->display, EGL_NO_SURFACE, EGL_NO_SURFACE, | ||||
| 			EGL_NO_CONTEXT)) { | ||||
| 		wlr_log(WLR_ERROR, "eglMakeCurrent failed"); | ||||
| 		return false; | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| bool wlr_egl_is_current(struct wlr_egl *egl) { | ||||
| 	return eglGetCurrentContext() == egl->context; | ||||
| } | ||||
|  | @ -690,7 +699,7 @@ bool wlr_egl_destroy_surface(struct wlr_egl *egl, EGLSurface surface) { | |||
| 		// Reset the current EGL surface in case it's the one we're destroying,
 | ||||
| 		// otherwise the next wlr_egl_make_current call will result in a
 | ||||
| 		// use-after-free.
 | ||||
| 		wlr_egl_make_current(egl, NULL, NULL); | ||||
| 		wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); | ||||
| 	} | ||||
| 	return eglDestroySurface(egl->display, surface); | ||||
| } | ||||
|  |  | |||
|  | @ -401,6 +401,8 @@ static void gles2_destroy(struct wlr_renderer *wlr_renderer) { | |||
| 		gles2_procs.glDebugMessageCallbackKHR(NULL, NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_egl_unset_current(renderer->egl); | ||||
| 
 | ||||
| 	free(renderer); | ||||
| } | ||||
| 
 | ||||
|  | @ -670,6 +672,8 @@ struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_egl *egl) { | |||
| 
 | ||||
| 	POP_GLES2_DEBUG; | ||||
| 
 | ||||
| 	wlr_egl_unset_current(renderer->egl); | ||||
| 
 | ||||
| 	return &renderer->wlr_renderer; | ||||
| 
 | ||||
| error: | ||||
|  | @ -686,6 +690,8 @@ error: | |||
| 		gles2_procs.glDebugMessageCallbackKHR(NULL, NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_egl_unset_current(renderer->egl); | ||||
| 
 | ||||
| 	free(renderer); | ||||
| 	return NULL; | ||||
| } | ||||
|  |  | |||
|  | @ -29,9 +29,7 @@ struct wlr_gles2_texture *gles2_get_texture( | |||
| static struct wlr_gles2_texture *get_gles2_texture_in_context( | ||||
| 		struct wlr_texture *wlr_texture) { | ||||
| 	struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); | ||||
| 	if (!wlr_egl_is_current(texture->egl)) { | ||||
| 		wlr_egl_make_current(texture->egl, EGL_NO_SURFACE, NULL); | ||||
| 	} | ||||
| 	wlr_egl_make_current(texture->egl, EGL_NO_SURFACE, NULL); | ||||
| 	return texture; | ||||
| } | ||||
| 
 | ||||
|  | @ -49,6 +47,7 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, | |||
| 
 | ||||
| 	if (texture->target != GL_TEXTURE_2D) { | ||||
| 		wlr_log(WLR_ERROR, "Cannot write pixels to immutable texture"); | ||||
| 		wlr_egl_unset_current(texture->egl); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
|  | @ -75,6 +74,8 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, | |||
| 	glBindTexture(GL_TEXTURE_2D, 0); | ||||
| 
 | ||||
| 	POP_GLES2_DEBUG; | ||||
| 
 | ||||
| 	wlr_egl_unset_current(texture->egl); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
|  | @ -111,11 +112,8 @@ static void gles2_texture_destroy(struct wlr_texture *wlr_texture) { | |||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); | ||||
| 
 | ||||
| 	if (!wlr_egl_is_current(texture->egl)) { | ||||
| 		wlr_egl_make_current(texture->egl, EGL_NO_SURFACE, NULL); | ||||
| 	} | ||||
| 	struct wlr_gles2_texture *texture = | ||||
| 		get_gles2_texture_in_context(wlr_texture); | ||||
| 
 | ||||
| 	PUSH_GLES2_DEBUG; | ||||
| 
 | ||||
|  | @ -124,6 +122,8 @@ static void gles2_texture_destroy(struct wlr_texture *wlr_texture) { | |||
| 
 | ||||
| 	POP_GLES2_DEBUG; | ||||
| 
 | ||||
| 	wlr_egl_unset_current(texture->egl); | ||||
| 
 | ||||
| 	free(texture); | ||||
| } | ||||
| 
 | ||||
|  | @ -137,9 +137,7 @@ static const struct wlr_texture_impl texture_impl = { | |||
| struct wlr_texture *wlr_gles2_texture_from_pixels(struct wlr_egl *egl, | ||||
| 		enum wl_shm_format wl_fmt, uint32_t stride, uint32_t width, | ||||
| 		uint32_t height, const void *data) { | ||||
| 	if (!wlr_egl_is_current(egl)) { | ||||
| 		wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); | ||||
| 	} | ||||
| 	wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); | ||||
| 
 | ||||
| 	const struct wlr_gles2_pixel_format *fmt = get_gles2_format_from_wl(wl_fmt); | ||||
| 	if (fmt == NULL) { | ||||
|  | @ -172,14 +170,14 @@ struct wlr_texture *wlr_gles2_texture_from_pixels(struct wlr_egl *egl, | |||
| 	glBindTexture(GL_TEXTURE_2D, 0); | ||||
| 
 | ||||
| 	POP_GLES2_DEBUG; | ||||
| 
 | ||||
| 	wlr_egl_unset_current(egl); | ||||
| 	return &texture->wlr_texture; | ||||
| } | ||||
| 
 | ||||
| struct wlr_texture *wlr_gles2_texture_from_wl_drm(struct wlr_egl *egl, | ||||
| 		struct wl_resource *resource) { | ||||
| 	if (!wlr_egl_is_current(egl)) { | ||||
| 		wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); | ||||
| 	} | ||||
| 	wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); | ||||
| 
 | ||||
| 	if (!gles2_procs.glEGLImageTargetTexture2DOES) { | ||||
| 		return NULL; | ||||
|  | @ -235,14 +233,14 @@ struct wlr_texture *wlr_gles2_texture_from_wl_drm(struct wlr_egl *egl, | |||
| 	glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); | ||||
| 
 | ||||
| 	POP_GLES2_DEBUG; | ||||
| 
 | ||||
| 	wlr_egl_unset_current(egl); | ||||
| 	return &texture->wlr_texture; | ||||
| } | ||||
| 
 | ||||
| struct wlr_texture *wlr_gles2_texture_from_dmabuf(struct wlr_egl *egl, | ||||
| 		struct wlr_dmabuf_attributes *attribs) { | ||||
| 	if (!wlr_egl_is_current(egl)) { | ||||
| 		wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); | ||||
| 	} | ||||
| 	wlr_egl_make_current(egl, EGL_NO_SURFACE, NULL); | ||||
| 
 | ||||
| 	if (!gles2_procs.glEGLImageTargetTexture2DOES) { | ||||
| 		return NULL; | ||||
|  | @ -297,6 +295,8 @@ struct wlr_texture *wlr_gles2_texture_from_dmabuf(struct wlr_egl *egl, | |||
| 	glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0); | ||||
| 
 | ||||
| 	POP_GLES2_DEBUG; | ||||
| 
 | ||||
| 	wlr_egl_unset_current(egl); | ||||
| 	return &texture->wlr_texture; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Simon Ser
						Simon Ser