mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-10-29 05:40:12 -04:00 
			
		
		
		
	render/gles2: remove global state, use OpenGL debug extension
This commit is contained in:
		
							parent
							
								
									ff2e08aa74
								
							
						
					
					
						commit
						95e86e675a
					
				
					 10 changed files with 526 additions and 372 deletions
				
			
		|  | @ -17,17 +17,24 @@ | |||
| 
 | ||||
| extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; | ||||
| 
 | ||||
| struct pixel_format { | ||||
| struct gles2_pixel_format { | ||||
| 	uint32_t wl_format; | ||||
| 	GLint gl_format, gl_type; | ||||
| 	int depth, bpp; | ||||
| 	GLuint *shader; | ||||
| }; | ||||
| 
 | ||||
| struct wlr_gles2_renderer { | ||||
| 	struct wlr_renderer wlr_renderer; | ||||
| 
 | ||||
| 	struct wlr_egl *egl; | ||||
| 
 | ||||
| 	struct { | ||||
| 		GLuint quad; | ||||
| 		GLuint ellipse; | ||||
| 		GLuint tex_rgba; | ||||
| 		GLuint tex_rgbx; | ||||
| 		GLuint tex_ext; | ||||
| 	} shaders; | ||||
| }; | ||||
| 
 | ||||
| struct wlr_gles2_texture { | ||||
|  | @ -35,37 +42,19 @@ struct wlr_gles2_texture { | |||
| 
 | ||||
| 	struct wlr_egl *egl; | ||||
| 	GLuint tex_id; | ||||
| 	const struct pixel_format *pixel_format; | ||||
| 	const struct gles2_pixel_format *pixel_format; | ||||
| 	EGLImageKHR image; | ||||
| 	GLenum target; | ||||
| }; | ||||
| 
 | ||||
| struct shaders { | ||||
| 	bool initialized; | ||||
| 	GLuint rgba, rgbx; | ||||
| 	GLuint quad; | ||||
| 	GLuint ellipse; | ||||
| 	GLuint external; | ||||
| }; | ||||
| 
 | ||||
| extern struct shaders shaders; | ||||
| 
 | ||||
| const struct pixel_format *gl_format_for_wl_format(enum wl_shm_format fmt); | ||||
| const struct gles2_pixel_format *gles2_format_from_wl(enum wl_shm_format fmt); | ||||
| 
 | ||||
| struct wlr_texture *gles2_texture_create(); | ||||
| struct wlr_gles2_texture *gles2_get_texture(struct wlr_texture *wlr_texture); | ||||
| 
 | ||||
| extern const GLchar quad_vertex_src[]; | ||||
| extern const GLchar quad_fragment_src[]; | ||||
| extern const GLchar ellipse_fragment_src[]; | ||||
| extern const GLchar vertex_src[]; | ||||
| extern const GLchar fragment_src_rgba[]; | ||||
| extern const GLchar fragment_src_rgbx[]; | ||||
| extern const GLchar fragment_src_external[]; | ||||
| 
 | ||||
| bool _gles2_flush_errors(const char *file, int line); | ||||
| #define gles2_flush_errors(...) \ | ||||
| 	_gles2_flush_errors(wlr_strip_path(__FILE__), __LINE__) | ||||
| 
 | ||||
| #define GL_CALL(func) func; gles2_flush_errors() | ||||
| void gles2_push_marker(const char *file, const char *func); | ||||
| void gles2_pop_marker(void); | ||||
| #define GLES2_DEBUG_PUSH gles2_push_marker(wlr_strip_path(__FILE__), __func__) | ||||
| #define GLES2_DEBUG_POP gles2_pop_marker() | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ | |||
| struct wlr_renderer_impl; | ||||
| 
 | ||||
| struct wlr_renderer { | ||||
| 	struct wlr_renderer_impl *impl; | ||||
| 	const struct wlr_renderer_impl *impl; | ||||
| }; | ||||
| 
 | ||||
| struct wlr_renderer_impl { | ||||
|  | @ -44,7 +44,7 @@ struct wlr_renderer_impl { | |||
| }; | ||||
| 
 | ||||
| void wlr_renderer_init(struct wlr_renderer *renderer, | ||||
| 		struct wlr_renderer_impl *impl); | ||||
| 		const struct wlr_renderer_impl *impl); | ||||
| 
 | ||||
| struct wlr_texture_impl { | ||||
| 	bool (*upload_pixels)(struct wlr_texture *texture, | ||||
|  | @ -65,13 +65,11 @@ struct wlr_texture_impl { | |||
| 		struct wl_resource *dmabuf_resource); | ||||
| 	void (*get_buffer_size)(struct wlr_texture *texture, | ||||
| 		struct wl_resource *resource, int *width, int *height); | ||||
| 	void (*bind)(struct wlr_texture *texture); | ||||
| 	void (*destroy)(struct wlr_texture *texture); | ||||
| }; | ||||
| 
 | ||||
| void wlr_texture_init(struct wlr_texture *texture, | ||||
| 		struct wlr_texture_impl *impl); | ||||
| void wlr_texture_bind(struct wlr_texture *texture); | ||||
| 	const struct wlr_texture_impl *impl); | ||||
| void wlr_texture_get_buffer_size(struct wlr_texture *texture, | ||||
| 	struct wl_resource *resource, int *width, int *height); | ||||
| 
 | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ | |||
| struct wlr_texture_impl; | ||||
| 
 | ||||
| struct wlr_texture { | ||||
| 	struct wlr_texture_impl *impl; | ||||
| 	const struct wlr_texture_impl *impl; | ||||
| 
 | ||||
| 	bool valid; | ||||
| 	uint32_t format; | ||||
|  |  | |||
|  | @ -10,3 +10,8 @@ eglCreatePlatformWindowSurfaceEXT | |||
| -eglSwapBuffersWithDamageKHR | ||||
| -eglQueryDmaBufFormatsEXT | ||||
| -eglQueryDmaBufModifiersEXT | ||||
| -eglDebugMessageControlKHR | ||||
| -glDebugMessageCallbackKHR | ||||
| -glDebugMessageControlKHR | ||||
| -glPopDebugGroupKHR | ||||
| -glPushDebugGroupKHR | ||||
|  |  | |||
|  | @ -6,14 +6,13 @@ | |||
| * The wayland formats are little endian while the GL formats are big endian, | ||||
| * so WL_SHM_FORMAT_ARGB8888 is actually compatible with GL_BGRA_EXT. | ||||
| */ | ||||
| struct pixel_format formats[] = { | ||||
| struct gles2_pixel_format formats[] = { | ||||
| 	{ | ||||
| 		.wl_format = WL_SHM_FORMAT_ARGB8888, | ||||
| 		.depth = 32, | ||||
| 		.bpp = 32, | ||||
| 		.gl_format = GL_BGRA_EXT, | ||||
| 		.gl_type = GL_UNSIGNED_BYTE, | ||||
| 		.shader = &shaders.rgba | ||||
| 	}, | ||||
| 	{ | ||||
| 		.wl_format = WL_SHM_FORMAT_XRGB8888, | ||||
|  | @ -21,7 +20,6 @@ struct pixel_format formats[] = { | |||
| 		.bpp = 32, | ||||
| 		.gl_format = GL_BGRA_EXT, | ||||
| 		.gl_type = GL_UNSIGNED_BYTE, | ||||
| 		.shader = &shaders.rgbx | ||||
| 	}, | ||||
| 	{ | ||||
| 		.wl_format = WL_SHM_FORMAT_XBGR8888, | ||||
|  | @ -29,7 +27,6 @@ struct pixel_format formats[] = { | |||
| 		.bpp = 32, | ||||
| 		.gl_format = GL_RGBA, | ||||
| 		.gl_type = GL_UNSIGNED_BYTE, | ||||
| 		.shader = &shaders.rgbx | ||||
| 	}, | ||||
| 	{ | ||||
| 		.wl_format = WL_SHM_FORMAT_ABGR8888, | ||||
|  | @ -37,12 +34,11 @@ struct pixel_format formats[] = { | |||
| 		.bpp = 32, | ||||
| 		.gl_format = GL_RGBA, | ||||
| 		.gl_type = GL_UNSIGNED_BYTE, | ||||
| 		.shader = &shaders.rgba | ||||
| 	}, | ||||
| }; | ||||
| // TODO: more pixel formats
 | ||||
| 
 | ||||
| const struct pixel_format *gl_format_for_wl_format(enum wl_shm_format fmt) { | ||||
| const struct gles2_pixel_format *gles2_format_from_wl(enum wl_shm_format fmt) { | ||||
| 	for (size_t i = 0; i < sizeof(formats) / sizeof(*formats); ++i) { | ||||
| 		if (formats[i].wl_format == fmt) { | ||||
| 			return &formats[i]; | ||||
|  |  | |||
|  | @ -2,145 +2,80 @@ | |||
| #include <GLES2/gl2.h> | ||||
| #include <GLES2/gl2ext.h> | ||||
| #include <stdint.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <wayland-server-protocol.h> | ||||
| #include <wayland-util.h> | ||||
| #include <wlr/backend.h> | ||||
| #include <wlr/render/wlr_renderer.h> | ||||
| #include <wlr/render/egl.h> | ||||
| #include <wlr/render/interface.h> | ||||
| #include <wlr/render/wlr_renderer.h> | ||||
| #include <wlr/types/wlr_matrix.h> | ||||
| #include <wlr/util/log.h> | ||||
| #include "render/gles2.h" | ||||
| #include "glapi.h" | ||||
| 
 | ||||
| struct shaders shaders; | ||||
| static const struct wlr_renderer_impl renderer_impl; | ||||
| 
 | ||||
| static bool compile_shader(GLuint type, const GLchar *src, GLuint *shader) { | ||||
| 	*shader = GL_CALL(glCreateShader(type)); | ||||
| 	int len = strlen(src); | ||||
| 	GL_CALL(glShaderSource(*shader, 1, &src, &len)); | ||||
| 	GL_CALL(glCompileShader(*shader)); | ||||
| 	GLint success; | ||||
| 	GL_CALL(glGetShaderiv(*shader, GL_COMPILE_STATUS, &success)); | ||||
| 	if (success == GL_FALSE) { | ||||
| 		GLint loglen; | ||||
| 		GL_CALL(glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &loglen)); | ||||
| 		GLchar msg[loglen]; | ||||
| 		GL_CALL(glGetShaderInfoLog(*shader, loglen, &loglen, msg)); | ||||
| 		wlr_log(L_ERROR, "Shader compilation failed"); | ||||
| 		wlr_log(L_ERROR, "%s", msg); | ||||
| 		glDeleteShader(*shader); | ||||
| 		return false; | ||||
| 	} | ||||
| 	return true; | ||||
| static struct wlr_gles2_renderer *gles2_get_renderer( | ||||
| 		struct wlr_renderer *wlr_renderer) { | ||||
| 	assert(wlr_renderer->impl == &renderer_impl); | ||||
| 	struct wlr_gles2_renderer *renderer = | ||||
| 		(struct wlr_gles2_renderer *)wlr_renderer; | ||||
| 	assert(eglGetCurrentContext() == renderer->egl->context); | ||||
| 	return renderer; | ||||
| } | ||||
| 
 | ||||
| static bool compile_program(const GLchar *vert_src, | ||||
| 		const GLchar *frag_src, GLuint *program) { | ||||
| 	GLuint vertex, fragment; | ||||
| 	if (!compile_shader(GL_VERTEX_SHADER, vert_src, &vertex)) { | ||||
| 		return false; | ||||
| 	} | ||||
| 	if (!compile_shader(GL_FRAGMENT_SHADER, frag_src, &fragment)) { | ||||
| 		glDeleteShader(vertex); | ||||
| 		return false; | ||||
| 	} | ||||
| 	*program = GL_CALL(glCreateProgram()); | ||||
| 	GL_CALL(glAttachShader(*program, vertex)); | ||||
| 	GL_CALL(glAttachShader(*program, fragment)); | ||||
| 	GL_CALL(glLinkProgram(*program)); | ||||
| 	GLint success; | ||||
| 	GL_CALL(glGetProgramiv(*program, GL_LINK_STATUS, &success)); | ||||
| 	if (success == GL_FALSE) { | ||||
| 		GLint loglen; | ||||
| 		GL_CALL(glGetProgramiv(*program, GL_INFO_LOG_LENGTH, &loglen)); | ||||
| 		GLchar msg[loglen]; | ||||
| 		GL_CALL(glGetProgramInfoLog(*program, loglen, &loglen, msg)); | ||||
| 		wlr_log(L_ERROR, "Program link failed"); | ||||
| 		wlr_log(L_ERROR, "%s", msg); | ||||
| 		glDeleteProgram(*program); | ||||
| 		glDeleteShader(vertex); | ||||
| 		glDeleteShader(fragment); | ||||
| 		return false; | ||||
| 	} | ||||
| 	glDetachShader(*program, vertex); | ||||
| 	glDetachShader(*program, fragment); | ||||
| 	glDeleteShader(vertex); | ||||
| 	glDeleteShader(fragment); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void init_default_shaders() { | ||||
| 	if (shaders.initialized) { | ||||
| 		return; | ||||
| 	} | ||||
| 	if (!compile_program(vertex_src, fragment_src_rgba, &shaders.rgba)) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 	if (!compile_program(vertex_src, fragment_src_rgbx, &shaders.rgbx)) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 	if (!compile_program(quad_vertex_src, quad_fragment_src, &shaders.quad)) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 	if (!compile_program(quad_vertex_src, ellipse_fragment_src, | ||||
| 			&shaders.ellipse)) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 	if (glEGLImageTargetTexture2DOES) { | ||||
| 		if (!compile_program(vertex_src, fragment_src_external, | ||||
| 				&shaders.external)) { | ||||
| 			goto error; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	wlr_log(L_DEBUG, "Compiled default shaders"); | ||||
| 	shaders.initialized = true; | ||||
| 	return; | ||||
| error: | ||||
| 	wlr_log(L_ERROR, "Failed to set up default shaders!"); | ||||
| } | ||||
| 
 | ||||
| static void init_globals() { | ||||
| 	init_default_shaders(); | ||||
| } | ||||
| 
 | ||||
| static void wlr_gles2_begin(struct wlr_renderer *wlr_renderer, | ||||
| static void gles2_begin(struct wlr_renderer *wlr_renderer, | ||||
| 		struct wlr_output *output) { | ||||
| 	GL_CALL(glViewport(0, 0, output->width, output->height)); | ||||
| 	gles2_get_renderer(wlr_renderer); | ||||
| 
 | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 
 | ||||
| 	glViewport(0, 0, output->width, output->height); | ||||
| 
 | ||||
| 	// enable transparency
 | ||||
| 	GL_CALL(glEnable(GL_BLEND)); | ||||
| 	GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); | ||||
| 	glEnable(GL_BLEND); | ||||
| 	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | ||||
| 
 | ||||
| 	// Note: maybe we should save output projection and remove some of the need
 | ||||
| 	// XXX: maybe we should save output projection and remove some of the need
 | ||||
| 	// for users to sling matricies themselves
 | ||||
| 
 | ||||
| 	GLES2_DEBUG_POP; | ||||
| } | ||||
| 
 | ||||
| static void wlr_gles2_end(struct wlr_renderer *wlr_renderer) { | ||||
| static void gles2_end(struct wlr_renderer *wlr_renderer) { | ||||
| 	gles2_get_renderer(wlr_renderer); | ||||
| 	// no-op
 | ||||
| } | ||||
| 
 | ||||
| static void wlr_gles2_clear(struct wlr_renderer *wlr_renderer, | ||||
| static void gles2_clear(struct wlr_renderer *wlr_renderer, | ||||
| 		const float color[static 4]) { | ||||
| 	gles2_get_renderer(wlr_renderer); | ||||
| 
 | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	glClearColor(color[0], color[1], color[2], color[3]); | ||||
| 	glClear(GL_COLOR_BUFFER_BIT); | ||||
| 	GLES2_DEBUG_POP; | ||||
| } | ||||
| 
 | ||||
| static void wlr_gles2_scissor(struct wlr_renderer *wlr_renderer, | ||||
| static void gles2_scissor(struct wlr_renderer *wlr_renderer, | ||||
| 		struct wlr_box *box) { | ||||
| 	gles2_get_renderer(wlr_renderer); | ||||
| 
 | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	if (box != NULL) { | ||||
| 		glScissor(box->x, box->y, box->width, box->height); | ||||
| 		glEnable(GL_SCISSOR_TEST); | ||||
| 	} else { | ||||
| 		glDisable(GL_SCISSOR_TEST); | ||||
| 	} | ||||
| 	GLES2_DEBUG_POP; | ||||
| } | ||||
| 
 | ||||
| static struct wlr_texture *wlr_gles2_texture_create( | ||||
| static struct wlr_texture *gles2_renderer_texture_create( | ||||
| 		struct wlr_renderer *wlr_renderer) { | ||||
| 	assert(wlr_renderer->impl == &renderer_impl); | ||||
| 	struct wlr_gles2_renderer *renderer = | ||||
| 		(struct wlr_gles2_renderer *)wlr_renderer; | ||||
| 	return gles2_texture_create(renderer->egl); | ||||
|  | @ -160,69 +95,93 @@ static void draw_quad() { | |||
| 		0, 1, // bottom left
 | ||||
| 	}; | ||||
| 
 | ||||
| 	GL_CALL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts)); | ||||
| 	GL_CALL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord)); | ||||
| 	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts); | ||||
| 	glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord); | ||||
| 
 | ||||
| 	GL_CALL(glEnableVertexAttribArray(0)); | ||||
| 	GL_CALL(glEnableVertexAttribArray(1)); | ||||
| 	glEnableVertexAttribArray(0); | ||||
| 	glEnableVertexAttribArray(1); | ||||
| 
 | ||||
| 	GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4)); | ||||
| 	glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | ||||
| 
 | ||||
| 	GL_CALL(glDisableVertexAttribArray(0)); | ||||
| 	GL_CALL(glDisableVertexAttribArray(1)); | ||||
| 	glDisableVertexAttribArray(0); | ||||
| 	glDisableVertexAttribArray(1); | ||||
| } | ||||
| 
 | ||||
| static bool wlr_gles2_render_texture_with_matrix( | ||||
| 		struct wlr_renderer *wlr_renderer, struct wlr_texture *texture, | ||||
| static bool gles2_render_texture_with_matrix( | ||||
| 		struct wlr_renderer *wlr_renderer, struct wlr_texture *wlr_texture, | ||||
| 		const float matrix[static 9], float alpha) { | ||||
| 	if (!texture || !texture->valid) { | ||||
| 	struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); | ||||
| 	struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); | ||||
| 	if (!wlr_texture->valid) { | ||||
| 		wlr_log(L_ERROR, "attempt to render invalid texture"); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	GLuint prog = renderer->shaders.tex_rgba; | ||||
| 	if (texture->target == GL_TEXTURE_EXTERNAL_OES) { | ||||
| 		prog = renderer->shaders.tex_ext; | ||||
| 	} else if (texture->pixel_format->wl_format == WL_SHM_FORMAT_XRGB8888 || | ||||
| 			texture->pixel_format->wl_format == WL_SHM_FORMAT_XBGR8888) { | ||||
| 		prog = renderer->shaders.tex_rgbx; | ||||
| 	} | ||||
| 
 | ||||
| 	// OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set
 | ||||
| 	// to GL_FALSE
 | ||||
| 	float transposition[9]; | ||||
| 	wlr_matrix_transpose(transposition, matrix); | ||||
| 
 | ||||
| 	wlr_texture_bind(texture); | ||||
| 	GL_CALL(glUniformMatrix3fv(0, 1, GL_FALSE, transposition)); | ||||
| 	GL_CALL(glUniform1i(1, texture->inverted_y)); | ||||
| 	GL_CALL(glUniform1f(3, alpha)); | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	glBindTexture(texture->target, texture->tex_id); | ||||
| 	glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | ||||
| 	glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | ||||
| 	glUseProgram(prog); | ||||
| 
 | ||||
| 	glUniformMatrix3fv(0, 1, GL_FALSE, transposition); | ||||
| 	glUniform1i(1, wlr_texture->inverted_y); | ||||
| 	glUniform1f(3, alpha); | ||||
| 	draw_quad(); | ||||
| 	GLES2_DEBUG_POP; | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static void wlr_gles2_render_quad(struct wlr_renderer *wlr_renderer, | ||||
| static void gles2_render_quad(struct wlr_renderer *wlr_renderer, | ||||
| 		const float color[static 4], const float matrix[static 9]) { | ||||
| 	struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); | ||||
| 
 | ||||
| 	// OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set
 | ||||
| 	// to GL_FALSE
 | ||||
| 	float transposition[9]; | ||||
| 	wlr_matrix_transpose(transposition, matrix); | ||||
| 
 | ||||
| 	GL_CALL(glUseProgram(shaders.quad)); | ||||
| 	GL_CALL(glUniformMatrix3fv(0, 1, GL_FALSE, transposition)); | ||||
| 	GL_CALL(glUniform4f(1, color[0], color[1], color[2], color[3])); | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	glUseProgram(renderer->shaders.quad); | ||||
| 	glUniformMatrix3fv(0, 1, GL_FALSE, transposition); | ||||
| 	glUniform4f(1, color[0], color[1], color[2], color[3]); | ||||
| 	draw_quad(); | ||||
| 	GLES2_DEBUG_POP; | ||||
| } | ||||
| 
 | ||||
| static void wlr_gles2_render_ellipse(struct wlr_renderer *wlr_renderer, | ||||
| static void gles2_render_ellipse(struct wlr_renderer *wlr_renderer, | ||||
| 		const float color[static 4], const float matrix[static 9]) { | ||||
| 	struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); | ||||
| 
 | ||||
| 	// OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set
 | ||||
| 	// to GL_FALSE
 | ||||
| 	float transposition[9]; | ||||
| 	wlr_matrix_transpose(transposition, matrix); | ||||
| 
 | ||||
| 	GL_CALL(glUseProgram(shaders.ellipse)); | ||||
| 	GL_CALL(glUniformMatrix3fv(0, 1, GL_FALSE, transposition)); | ||||
| 	GL_CALL(glUniform4f(1, color[0], color[1], color[2], color[3])); | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	glUseProgram(renderer->shaders.ellipse); | ||||
| 	glUniformMatrix3fv(0, 1, GL_FALSE, transposition); | ||||
| 	glUniform4f(1, color[0], color[1], color[2], color[3]); | ||||
| 	draw_quad(); | ||||
| 	GLES2_DEBUG_POP; | ||||
| } | ||||
| 
 | ||||
| static const enum wl_shm_format *wlr_gles2_formats( | ||||
| static const enum wl_shm_format *gles2_formats( | ||||
| 		struct wlr_renderer *renderer, size_t *len) { | ||||
| 	static enum wl_shm_format formats[] = { | ||||
| 	static const enum wl_shm_format formats[] = { | ||||
| 		WL_SHM_FORMAT_ARGB8888, | ||||
| 		WL_SHM_FORMAT_XRGB8888, | ||||
| 		WL_SHM_FORMAT_ABGR8888, | ||||
|  | @ -232,25 +191,29 @@ static const enum wl_shm_format *wlr_gles2_formats( | |||
| 	return formats; | ||||
| } | ||||
| 
 | ||||
| static bool wlr_gles2_buffer_is_drm(struct wlr_renderer *wlr_renderer, | ||||
| static bool gles2_buffer_is_drm(struct wlr_renderer *wlr_renderer, | ||||
| 		struct wl_resource *buffer) { | ||||
| 	struct wlr_gles2_renderer *renderer = | ||||
| 		(struct wlr_gles2_renderer *)wlr_renderer; | ||||
| 	struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); | ||||
| 
 | ||||
| 	EGLint format; | ||||
| 	return wlr_egl_query_buffer(renderer->egl, buffer, | ||||
| 		EGL_TEXTURE_FORMAT, &format); | ||||
| 	return wlr_egl_query_buffer(renderer->egl, buffer, EGL_TEXTURE_FORMAT, | ||||
| 		&format); | ||||
| } | ||||
| 
 | ||||
| static bool wlr_gles2_read_pixels(struct wlr_renderer *renderer, | ||||
| static bool gles2_read_pixels(struct wlr_renderer *wlr_renderer, | ||||
| 		enum wl_shm_format wl_fmt, uint32_t stride, uint32_t width, | ||||
| 		uint32_t height, uint32_t src_x, uint32_t src_y, uint32_t dst_x, | ||||
| 		uint32_t dst_y, void *data) { | ||||
| 	const struct pixel_format *fmt = gl_format_for_wl_format(wl_fmt); | ||||
| 	gles2_get_renderer(wlr_renderer); | ||||
| 
 | ||||
| 	const struct gles2_pixel_format *fmt = gles2_format_from_wl(wl_fmt); | ||||
| 	if (fmt == NULL) { | ||||
| 		wlr_log(L_ERROR, "Cannot read pixels: unsupported pixel format"); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 
 | ||||
| 	// Make sure any pending drawing is finished before we try to read it
 | ||||
| 	glFinish(); | ||||
| 
 | ||||
|  | @ -262,38 +225,225 @@ static bool wlr_gles2_read_pixels(struct wlr_renderer *renderer, | |||
| 			fmt->gl_type, p + i * stride + dst_x * fmt->bpp / 8); | ||||
| 	} | ||||
| 
 | ||||
| 	GLES2_DEBUG_POP; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static bool wlr_gles2_format_supported(struct wlr_renderer *r, | ||||
| static bool gles2_format_supported(struct wlr_renderer *r, | ||||
| 		enum wl_shm_format wl_fmt) { | ||||
| 	return gl_format_for_wl_format(wl_fmt); | ||||
| 	return gles2_format_from_wl(wl_fmt) != NULL; | ||||
| } | ||||
| 
 | ||||
| static struct wlr_renderer_impl wlr_renderer_impl = { | ||||
| 	.begin = wlr_gles2_begin, | ||||
| 	.end = wlr_gles2_end, | ||||
| 	.clear = wlr_gles2_clear, | ||||
| 	.scissor = wlr_gles2_scissor, | ||||
| 	.texture_create = wlr_gles2_texture_create, | ||||
| 	.render_texture_with_matrix = wlr_gles2_render_texture_with_matrix, | ||||
| 	.render_quad = wlr_gles2_render_quad, | ||||
| 	.render_ellipse = wlr_gles2_render_ellipse, | ||||
| 	.formats = wlr_gles2_formats, | ||||
| 	.buffer_is_drm = wlr_gles2_buffer_is_drm, | ||||
| 	.read_pixels = wlr_gles2_read_pixels, | ||||
| 	.format_supported = wlr_gles2_format_supported, | ||||
| static void gles2_destroy(struct wlr_renderer *wlr_renderer) { | ||||
| 	struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer); | ||||
| 
 | ||||
| 	wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL); | ||||
| 
 | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	glDeleteProgram(renderer->shaders.quad); | ||||
| 	glDeleteProgram(renderer->shaders.ellipse); | ||||
| 	glDeleteProgram(renderer->shaders.tex_rgba); | ||||
| 	glDeleteProgram(renderer->shaders.tex_rgbx); | ||||
| 	glDeleteProgram(renderer->shaders.tex_ext); | ||||
| 	GLES2_DEBUG_POP; | ||||
| 
 | ||||
| 	if (glDebugMessageCallbackKHR) { | ||||
| 		glDisable(GL_DEBUG_OUTPUT_KHR); | ||||
| 		glDebugMessageCallbackKHR(NULL, NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	free(renderer); | ||||
| } | ||||
| 
 | ||||
| static const struct wlr_renderer_impl renderer_impl = { | ||||
| 	.destroy = gles2_destroy, | ||||
| 	.begin = gles2_begin, | ||||
| 	.end = gles2_end, | ||||
| 	.clear = gles2_clear, | ||||
| 	.scissor = gles2_scissor, | ||||
| 	.texture_create = gles2_renderer_texture_create, | ||||
| 	.render_texture_with_matrix = gles2_render_texture_with_matrix, | ||||
| 	.render_quad = gles2_render_quad, | ||||
| 	.render_ellipse = gles2_render_ellipse, | ||||
| 	.formats = gles2_formats, | ||||
| 	.buffer_is_drm = gles2_buffer_is_drm, | ||||
| 	.read_pixels = gles2_read_pixels, | ||||
| 	.format_supported = gles2_format_supported, | ||||
| }; | ||||
| 
 | ||||
| void gles2_push_marker(const char *file, const char *func) { | ||||
| 	if (!glPushDebugGroupKHR) { | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	int len = snprintf(NULL, 0, "%s:%s", file, func) + 1; | ||||
| 	char str[len]; | ||||
| 	snprintf(str, len, "%s:%s", file, func); | ||||
| 	glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION_KHR, 1, -1, str); | ||||
| } | ||||
| 
 | ||||
| void gles2_pop_marker(void) { | ||||
| 	if (glPopDebugGroupKHR) { | ||||
| 		glPopDebugGroupKHR(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static log_importance_t gles2_log_importance_to_wlr(GLenum type) { | ||||
| 	switch (type) { | ||||
| 	case GL_DEBUG_TYPE_ERROR_KHR:               return L_ERROR; | ||||
| 	case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR: return L_DEBUG; | ||||
| 	case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR:  return L_ERROR; | ||||
| 	case GL_DEBUG_TYPE_PORTABILITY_KHR:         return L_DEBUG; | ||||
| 	case GL_DEBUG_TYPE_PERFORMANCE_KHR:         return L_DEBUG; | ||||
| 	case GL_DEBUG_TYPE_OTHER_KHR:               return L_INFO; | ||||
| 	case GL_DEBUG_TYPE_MARKER_KHR:              return L_DEBUG; | ||||
| 	case GL_DEBUG_TYPE_PUSH_GROUP_KHR:          return L_DEBUG; | ||||
| 	case GL_DEBUG_TYPE_POP_GROUP_KHR:           return L_DEBUG; | ||||
| 	default:                                    return L_INFO; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void gles2_log(GLenum src, GLenum type, GLuint id, GLenum severity, | ||||
| 		GLsizei len, const GLchar *msg, const void *user) { | ||||
| 	_wlr_log(gles2_log_importance_to_wlr(type), "[GLES2] %s", msg); | ||||
| } | ||||
| 
 | ||||
| static GLuint compile_shader(GLuint type, const GLchar *src) { | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 
 | ||||
| 	GLuint shader = glCreateShader(type); | ||||
| 	glShaderSource(shader, 1, &src, NULL); | ||||
| 	glCompileShader(shader); | ||||
| 
 | ||||
| 	GLint ok; | ||||
| 	glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); | ||||
| 	if (ok == GL_FALSE) { | ||||
| 		glDeleteShader(shader); | ||||
| 		shader = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	GLES2_DEBUG_POP; | ||||
| 	return shader; | ||||
| } | ||||
| 
 | ||||
| static GLuint link_program(const GLchar *vert_src, const GLchar *frag_src) { | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 
 | ||||
| 	GLuint vert = compile_shader(GL_VERTEX_SHADER, vert_src); | ||||
| 	if (!vert) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 
 | ||||
| 	GLuint frag = compile_shader(GL_FRAGMENT_SHADER, frag_src); | ||||
| 	if (!frag) { | ||||
| 		glDeleteShader(vert); | ||||
| 		goto error; | ||||
| 	} | ||||
| 
 | ||||
| 	GLuint prog = glCreateProgram(); | ||||
| 	glAttachShader(prog, vert); | ||||
| 	glAttachShader(prog, frag); | ||||
| 	glLinkProgram(prog); | ||||
| 
 | ||||
| 	glDetachShader(prog, vert); | ||||
| 	glDetachShader(prog, frag); | ||||
| 	glDeleteShader(vert); | ||||
| 	glDeleteShader(frag); | ||||
| 
 | ||||
| 	GLint ok; | ||||
| 	glGetProgramiv(prog, GL_LINK_STATUS, &ok); | ||||
| 	if (ok == GL_FALSE) { | ||||
| 		glDeleteProgram(prog); | ||||
| 		goto error; | ||||
| 	} | ||||
| 
 | ||||
| 	GLES2_DEBUG_POP; | ||||
| 	return prog; | ||||
| 
 | ||||
| error: | ||||
| 	GLES2_DEBUG_POP; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| extern const GLchar quad_vertex_src[]; | ||||
| extern const GLchar quad_fragment_src[]; | ||||
| extern const GLchar ellipse_fragment_src[]; | ||||
| extern const GLchar tex_vertex_src[]; | ||||
| extern const GLchar tex_fragment_src_rgba[]; | ||||
| extern const GLchar tex_fragment_src_rgbx[]; | ||||
| extern const GLchar tex_fragment_src_external[]; | ||||
| 
 | ||||
| struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_backend *backend) { | ||||
| 	init_globals(); | ||||
| 	struct wlr_gles2_renderer *renderer; | ||||
| 	if (!(renderer = calloc(1, sizeof(struct wlr_gles2_renderer)))) { | ||||
| 	struct wlr_gles2_renderer *renderer = | ||||
| 		calloc(1, sizeof(struct wlr_gles2_renderer)); | ||||
| 	if (renderer == NULL) { | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	wlr_renderer_init(&renderer->wlr_renderer, &wlr_renderer_impl); | ||||
| 	wlr_renderer_init(&renderer->wlr_renderer, &renderer_impl); | ||||
| 
 | ||||
| 	renderer->egl = wlr_backend_get_egl(backend); | ||||
| 	wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL); | ||||
| 
 | ||||
| 	if (glDebugMessageCallbackKHR && glDebugMessageControlKHR) { | ||||
| 		glEnable(GL_DEBUG_OUTPUT_KHR); | ||||
| 		glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR); | ||||
| 		glDebugMessageCallbackKHR(gles2_log, NULL); | ||||
| 
 | ||||
| 		// Silence unwanted message types
 | ||||
| 		glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_POP_GROUP_KHR, | ||||
| 			GL_DONT_CARE, 0, NULL, GL_FALSE); | ||||
| 		glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_PUSH_GROUP_KHR, | ||||
| 			GL_DONT_CARE, 0, NULL, GL_FALSE); | ||||
| 	} | ||||
| 
 | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 
 | ||||
| 	renderer->shaders.quad = link_program(quad_vertex_src, quad_fragment_src); | ||||
| 	if (!renderer->shaders.quad) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 	renderer->shaders.ellipse = | ||||
| 		link_program(quad_vertex_src, ellipse_fragment_src); | ||||
| 	if (!renderer->shaders.ellipse) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 	renderer->shaders.tex_rgba = | ||||
| 		link_program(tex_vertex_src, tex_fragment_src_rgba); | ||||
| 	if (!renderer->shaders.tex_rgba) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 	renderer->shaders.tex_rgbx = | ||||
| 		link_program(tex_vertex_src, tex_fragment_src_rgbx); | ||||
| 	if (!renderer->shaders.tex_rgbx) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 	if (glEGLImageTargetTexture2DOES) { | ||||
| 		renderer->shaders.tex_ext = | ||||
| 			link_program(tex_vertex_src, tex_fragment_src_external); | ||||
| 		if (!renderer->shaders.tex_ext) { | ||||
| 			goto error; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	GLES2_DEBUG_POP; | ||||
| 
 | ||||
| 	return &renderer->wlr_renderer; | ||||
| 
 | ||||
| error: | ||||
| 	glDeleteProgram(renderer->shaders.quad); | ||||
| 	glDeleteProgram(renderer->shaders.ellipse); | ||||
| 	glDeleteProgram(renderer->shaders.tex_rgba); | ||||
| 	glDeleteProgram(renderer->shaders.tex_rgbx); | ||||
| 	glDeleteProgram(renderer->shaders.tex_ext); | ||||
| 
 | ||||
| 	GLES2_DEBUG_POP; | ||||
| 
 | ||||
| 	if (glDebugMessageCallbackKHR) { | ||||
| 		glDisable(GL_DEBUG_OUTPUT_KHR); | ||||
| 		glDebugMessageCallbackKHR(NULL, NULL); | ||||
| 	} | ||||
| 
 | ||||
| 	free(renderer); | ||||
| 	return NULL; | ||||
| } | ||||
|  |  | |||
|  | @ -3,86 +3,88 @@ | |||
| 
 | ||||
| // Colored quads
 | ||||
| const GLchar quad_vertex_src[] = | ||||
| "uniform mat3 proj;" | ||||
| "uniform vec4 color;" | ||||
| "attribute vec2 pos;" | ||||
| "attribute vec2 texcoord;" | ||||
| "varying vec4 v_color;" | ||||
| "varying vec2 v_texcoord;" | ||||
| "" | ||||
| "void main() {" | ||||
| "	gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);" | ||||
| "	v_color = color;" | ||||
| "	v_texcoord = texcoord;" | ||||
| "}"; | ||||
| "uniform mat3 proj;\n" | ||||
| "uniform vec4 color;\n" | ||||
| "attribute vec2 pos;\n" | ||||
| "attribute vec2 texcoord;\n" | ||||
| "varying vec4 v_color;\n" | ||||
| "varying vec2 v_texcoord;\n" | ||||
| "\n" | ||||
| "void main() {\n" | ||||
| "	gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);\n" | ||||
| "	v_color = color;\n" | ||||
| "	v_texcoord = texcoord;\n" | ||||
| "}\n"; | ||||
| 
 | ||||
| const GLchar quad_fragment_src[] = | ||||
| "precision mediump float;" | ||||
| "varying vec4 v_color;" | ||||
| "varying vec2 v_texcoord;" | ||||
| "" | ||||
| "void main() {" | ||||
| "  gl_FragColor = v_color;" | ||||
| "}"; | ||||
| "precision mediump float;\n" | ||||
| "varying vec4 v_color;\n" | ||||
| "varying vec2 v_texcoord;\n" | ||||
| "\n" | ||||
| "void main() {\n" | ||||
| "	gl_FragColor = v_color;\n" | ||||
| "}\n"; | ||||
| 
 | ||||
| // Colored ellipses
 | ||||
| const GLchar ellipse_fragment_src[] = | ||||
| "precision mediump float;" | ||||
| "varying vec4 v_color;" | ||||
| "varying vec2 v_texcoord;" | ||||
| "" | ||||
| "void main() {" | ||||
| "  float l = length(v_texcoord - vec2(0.5, 0.5));" | ||||
| "  if (l > 0.5) discard;" | ||||
| "  gl_FragColor = v_color;" | ||||
| "}"; | ||||
| "precision mediump float;\n" | ||||
| "varying vec4 v_color;\n" | ||||
| "varying vec2 v_texcoord;\n" | ||||
| "\n" | ||||
| "void main() {\n" | ||||
| "	float l = length(v_texcoord - vec2(0.5, 0.5));\n" | ||||
| "	if (l > 0.5) {\n" | ||||
| "		discard;\n" | ||||
| "	}\n" | ||||
| "	gl_FragColor = v_color;\n" | ||||
| "}\n"; | ||||
| 
 | ||||
| // Textured quads
 | ||||
| const GLchar vertex_src[] = | ||||
| "uniform mat3 proj;" | ||||
| "uniform bool invert_y;" | ||||
| "attribute vec2 pos;" | ||||
| "attribute vec2 texcoord;" | ||||
| "varying vec2 v_texcoord;" | ||||
| "" | ||||
| "void main() {" | ||||
| "  gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);" | ||||
| "  if (invert_y) {" | ||||
| "    v_texcoord = vec2(texcoord.s, 1.0 - texcoord.t);" | ||||
| "  } else {" | ||||
| "    v_texcoord = texcoord;" | ||||
| "  }" | ||||
| "}"; | ||||
| const GLchar tex_vertex_src[] = | ||||
| "uniform mat3 proj;\n" | ||||
| "uniform bool invert_y;\n" | ||||
| "attribute vec2 pos;\n" | ||||
| "attribute vec2 texcoord;\n" | ||||
| "varying vec2 v_texcoord;\n" | ||||
| "\n" | ||||
| "void main() {\n" | ||||
| "	gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);\n" | ||||
| "	if (invert_y) {\n" | ||||
| "		v_texcoord = vec2(texcoord.s, 1.0 - texcoord.t);\n" | ||||
| "	} else {\n" | ||||
| "		v_texcoord = texcoord;\n" | ||||
| "	}\n" | ||||
| "}\n"; | ||||
| 
 | ||||
| const GLchar fragment_src_rgba[] = | ||||
| "precision mediump float;" | ||||
| "varying vec2 v_texcoord;" | ||||
| "uniform sampler2D tex;" | ||||
| "uniform float alpha;" | ||||
| "" | ||||
| "void main() {" | ||||
| "	gl_FragColor = alpha * texture2D(tex, v_texcoord);" | ||||
| "}"; | ||||
| const GLchar tex_fragment_src_rgba[] = | ||||
| "precision mediump float;\n" | ||||
| "varying vec2 v_texcoord;\n" | ||||
| "uniform sampler2D tex;\n" | ||||
| "uniform float alpha;\n" | ||||
| "\n" | ||||
| "void main() {\n" | ||||
| "	gl_FragColor = alpha * texture2D(tex, v_texcoord);\n" | ||||
| "}\n"; | ||||
| 
 | ||||
| const GLchar fragment_src_rgbx[] = | ||||
| "precision mediump float;" | ||||
| "varying vec2 v_texcoord;" | ||||
| "uniform sampler2D tex;" | ||||
| "uniform float alpha;" | ||||
| "" | ||||
| "void main() {" | ||||
| "	gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb;" | ||||
| "	gl_FragColor.a = alpha;" | ||||
| "}"; | ||||
| const GLchar tex_fragment_src_rgbx[] = | ||||
| "precision mediump float;\n" | ||||
| "varying vec2 v_texcoord;\n" | ||||
| "uniform sampler2D tex;\n" | ||||
| "uniform float alpha;\n" | ||||
| "\n" | ||||
| "void main() {\n" | ||||
| "	gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb;\n" | ||||
| "	gl_FragColor.a = alpha;\n" | ||||
| "}\n"; | ||||
| 
 | ||||
| const GLchar fragment_src_external[] = | ||||
| "#extension GL_OES_EGL_image_external : require\n" | ||||
| "precision mediump float;" | ||||
| "varying vec2 v_texcoord;" | ||||
| "uniform samplerExternalOES texture0;" | ||||
| "uniform float alpha;" | ||||
| "" | ||||
| "void main() {" | ||||
| "	vec4 col = texture2D(texture0, v_texcoord);" | ||||
| "	gl_FragColor = vec4(col.rgb, col.a * alpha);" | ||||
| "}"; | ||||
| const GLchar tex_fragment_src_external[] = | ||||
| "#extension GL_OES_EGL_image_external : require\n\n" | ||||
| "precision mediump float;\n" | ||||
| "varying vec2 v_texcoord;\n" | ||||
| "uniform samplerExternalOES texture0;\n" | ||||
| "uniform float alpha;\n" | ||||
| "\n" | ||||
| "void main() {\n" | ||||
| "	vec4 col = texture2D(texture0, v_texcoord);\n" | ||||
| "	gl_FragColor = vec4(col.rgb, col.a * alpha);\n" | ||||
| "}\n"; | ||||
|  |  | |||
|  | @ -13,33 +13,39 @@ | |||
| #include "render/gles2.h" | ||||
| #include "util/signal.h" | ||||
| 
 | ||||
| static struct pixel_format external_pixel_format = { | ||||
| static struct gles2_pixel_format external_pixel_format = { | ||||
| 	.wl_format = 0, | ||||
| 	.depth = 0, | ||||
| 	.bpp = 0, | ||||
| 	.gl_format = 0, | ||||
| 	.gl_type = 0, | ||||
| 	.shader = &shaders.external | ||||
| }; | ||||
| 
 | ||||
| static void gles2_texture_ensure_texture(struct wlr_gles2_texture *texture, | ||||
| static void gles2_texture_ensure(struct wlr_gles2_texture *texture, | ||||
| 		GLenum target) { | ||||
| 	if (texture->tex_id) { | ||||
| 		return; | ||||
| 	} | ||||
| 	texture->target = target; | ||||
| 	GL_CALL(glGenTextures(1, &texture->tex_id)); | ||||
| 	GL_CALL(glBindTexture(target, texture->tex_id)); | ||||
| 	GL_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)); | ||||
| 	GL_CALL(glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)); | ||||
| 	glGenTextures(1, &texture->tex_id); | ||||
| 	glBindTexture(target, texture->tex_id); | ||||
| 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); | ||||
| 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); | ||||
| } | ||||
| 
 | ||||
| static bool gles2_texture_upload_pixels(struct wlr_texture *_texture, | ||||
| static const struct wlr_texture_impl texture_impl; | ||||
| 
 | ||||
| struct wlr_gles2_texture *gles2_get_texture(struct wlr_texture *wlr_texture) { | ||||
| 	assert(wlr_texture->impl == &texture_impl); | ||||
| 	return (struct wlr_gles2_texture *)wlr_texture; | ||||
| } | ||||
| 
 | ||||
| static bool gles2_texture_upload_pixels(struct wlr_texture *wlr_texture, | ||||
| 		enum wl_shm_format format, int stride, int width, int height, | ||||
| 		const unsigned char *pixels) { | ||||
| 	struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; | ||||
| 	assert(texture); | ||||
| 	const struct pixel_format *fmt = gl_format_for_wl_format(format); | ||||
| 	struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); | ||||
| 
 | ||||
| 	const struct gles2_pixel_format *fmt = gles2_format_from_wl(format); | ||||
| 	if (!fmt || !fmt->gl_format) { | ||||
| 		wlr_log(L_ERROR, "No supported pixel format for this texture"); | ||||
| 		return false; | ||||
|  | @ -49,44 +55,50 @@ static bool gles2_texture_upload_pixels(struct wlr_texture *_texture, | |||
| 	texture->wlr_texture.format = format; | ||||
| 	texture->pixel_format = fmt; | ||||
| 
 | ||||
| 	gles2_texture_ensure_texture(texture, GL_TEXTURE_2D); | ||||
| 	GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride)); | ||||
| 	GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0, | ||||
| 			fmt->gl_format, fmt->gl_type, pixels)); | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	gles2_texture_ensure(texture, GL_TEXTURE_2D); | ||||
| 	glBindTexture(GL_TEXTURE_2D, texture->tex_id); | ||||
| 	glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride); | ||||
| 	glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0, | ||||
| 		fmt->gl_format, fmt->gl_type, pixels); | ||||
| 	GLES2_DEBUG_POP; | ||||
| 
 | ||||
| 	texture->wlr_texture.valid = true; | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static bool gles2_texture_update_pixels(struct wlr_texture *_texture, | ||||
| static bool gles2_texture_update_pixels(struct wlr_texture *wlr_texture, | ||||
| 		enum wl_shm_format format, int stride, int x, int y, | ||||
| 		int width, int height, const unsigned char *pixels) { | ||||
| 	struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; | ||||
| 	assert(texture); | ||||
| 	struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); | ||||
| 
 | ||||
| 	// TODO: Test if the unpack subimage extension is supported and adjust the
 | ||||
| 	// upload strategy if not
 | ||||
| 	if (!texture->wlr_texture.valid | ||||
| 			|| texture->wlr_texture.format != format | ||||
| 		/*	|| unpack not supported */) { | ||||
| 		return gles2_texture_upload_pixels(&texture->wlr_texture, | ||||
| 				format, stride, width, height, pixels); | ||||
| 		return gles2_texture_upload_pixels(&texture->wlr_texture, format, | ||||
| 			stride, width, height, pixels); | ||||
| 	} | ||||
| 	const struct pixel_format *fmt = texture->pixel_format; | ||||
| 	GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y)); | ||||
| 	GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, | ||||
| 			fmt->gl_format, fmt->gl_type, pixels)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0)); | ||||
| 	const struct gles2_pixel_format *fmt = texture->pixel_format; | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	glBindTexture(GL_TEXTURE_2D, texture->tex_id); | ||||
| 	glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride); | ||||
| 	glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x); | ||||
| 	glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y); | ||||
| 	glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, fmt->gl_format, | ||||
| 		fmt->gl_type, pixels); | ||||
| 	glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0); | ||||
| 	glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0); | ||||
| 	GLES2_DEBUG_POP; | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static bool gles2_texture_upload_shm(struct wlr_texture *_texture, | ||||
| static bool gles2_texture_upload_shm(struct wlr_texture *wlr_texture, | ||||
| 		uint32_t format, struct wl_shm_buffer *buffer) { | ||||
| 	struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; | ||||
| 	const struct pixel_format *fmt = gl_format_for_wl_format(format); | ||||
| 	struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); | ||||
| 
 | ||||
| 	const struct gles2_pixel_format *fmt = gles2_format_from_wl(format); | ||||
| 	if (!fmt || !fmt->gl_format) { | ||||
| 		wlr_log(L_ERROR, "Unsupported pixel format %"PRIu32" for this texture", | ||||
| 				format); | ||||
|  | @ -102,23 +114,26 @@ static bool gles2_texture_upload_shm(struct wlr_texture *_texture, | |||
| 	texture->wlr_texture.format = format; | ||||
| 	texture->pixel_format = fmt; | ||||
| 
 | ||||
| 	gles2_texture_ensure_texture(texture, GL_TEXTURE_2D); | ||||
| 	GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0)); | ||||
| 	GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0, | ||||
| 				fmt->gl_format, fmt->gl_type, pixels)); | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	gles2_texture_ensure(texture, GL_TEXTURE_2D); | ||||
| 	glBindTexture(GL_TEXTURE_2D, texture->tex_id); | ||||
| 	glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch); | ||||
| 	glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0); | ||||
| 	glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0); | ||||
| 	glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0, | ||||
| 		fmt->gl_format, fmt->gl_type, pixels); | ||||
| 	GLES2_DEBUG_POP; | ||||
| 
 | ||||
| 	texture->wlr_texture.valid = true; | ||||
| 	wl_shm_buffer_end_access(buffer); | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static bool gles2_texture_update_shm(struct wlr_texture *_texture, | ||||
| static bool gles2_texture_update_shm(struct wlr_texture *wlr_texture, | ||||
| 		uint32_t format, int x, int y, int width, int height, | ||||
| 		struct wl_shm_buffer *buffer) { | ||||
| 	struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; | ||||
| 	struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); | ||||
| 
 | ||||
| 	// TODO: Test if the unpack subimage extension is supported and adjust the
 | ||||
| 	// upload strategy if not
 | ||||
| 	assert(texture); | ||||
|  | @ -127,28 +142,30 @@ static bool gles2_texture_update_shm(struct wlr_texture *_texture, | |||
| 		/*	|| unpack not supported */) { | ||||
| 		return gles2_texture_upload_shm(&texture->wlr_texture, format, buffer); | ||||
| 	} | ||||
| 	const struct pixel_format *fmt = texture->pixel_format; | ||||
| 	const struct gles2_pixel_format *fmt = texture->pixel_format; | ||||
| 	wl_shm_buffer_begin_access(buffer); | ||||
| 	uint8_t *pixels = wl_shm_buffer_get_data(buffer); | ||||
| 	int pitch = wl_shm_buffer_get_stride(buffer) / (fmt->bpp / 8); | ||||
| 
 | ||||
| 	GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y)); | ||||
| 	GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, | ||||
| 			fmt->gl_format, fmt->gl_type, pixels)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0)); | ||||
| 	GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0)); | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	glBindTexture(GL_TEXTURE_2D, texture->tex_id); | ||||
| 	glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch); | ||||
| 	glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x); | ||||
| 	glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y); | ||||
| 	glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, | ||||
| 			fmt->gl_format, fmt->gl_type, pixels); | ||||
| 	glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0); | ||||
| 	glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0); | ||||
| 	GLES2_DEBUG_POP; | ||||
| 
 | ||||
| 	wl_shm_buffer_end_access(buffer); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static bool gles2_texture_upload_drm(struct wlr_texture *_tex, | ||||
| static bool gles2_texture_upload_drm(struct wlr_texture *wlr_texture, | ||||
| 		struct wl_resource *buf) { | ||||
| 	struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)_tex; | ||||
| 	struct wlr_gles2_texture *tex = gles2_get_texture(wlr_texture); | ||||
| 	if (!glEGLImageTargetTexture2DOES) { | ||||
| 		return false; | ||||
| 	} | ||||
|  | @ -171,12 +188,12 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex, | |||
| 	} | ||||
| 
 | ||||
| 	GLenum target; | ||||
| 	const struct pixel_format *pf; | ||||
| 	const struct gles2_pixel_format *pf; | ||||
| 	switch (format) { | ||||
| 	case EGL_TEXTURE_RGB: | ||||
| 	case EGL_TEXTURE_RGBA: | ||||
| 		target = GL_TEXTURE_2D; | ||||
| 		pf = gl_format_for_wl_format(WL_SHM_FORMAT_ARGB8888); | ||||
| 		pf = gles2_format_from_wl(WL_SHM_FORMAT_ARGB8888); | ||||
| 		break; | ||||
| 	case EGL_TEXTURE_EXTERNAL_WL: | ||||
| 		target = GL_TEXTURE_EXTERNAL_OES; | ||||
|  | @ -187,8 +204,11 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex, | |||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	gles2_texture_ensure_texture(tex, target); | ||||
| 	GL_CALL(glBindTexture(GL_TEXTURE_2D, tex->tex_id)); | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	gles2_texture_ensure(tex, target); | ||||
| 	glBindTexture(GL_TEXTURE_2D, tex->tex_id); | ||||
| 	GLES2_DEBUG_POP; | ||||
| 
 | ||||
| 	EGLint attribs[] = { EGL_WAYLAND_PLANE_WL, 0, EGL_NONE }; | ||||
| 
 | ||||
| 	if (tex->image) { | ||||
|  | @ -202,18 +222,20 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex, | |||
|  		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	GL_CALL(glActiveTexture(GL_TEXTURE0)); | ||||
| 	GL_CALL(glBindTexture(target, tex->tex_id)); | ||||
| 	GL_CALL(glEGLImageTargetTexture2DOES(target, tex->image)); | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	glActiveTexture(GL_TEXTURE0); | ||||
| 	glBindTexture(target, tex->tex_id); | ||||
| 	glEGLImageTargetTexture2DOES(target, tex->image); | ||||
| 	GLES2_DEBUG_POP; | ||||
| 	tex->wlr_texture.valid = true; | ||||
| 	tex->pixel_format = pf; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static bool gles2_texture_upload_eglimage(struct wlr_texture *wlr_tex, | ||||
| static bool gles2_texture_upload_eglimage(struct wlr_texture *wlr_texture, | ||||
| 		EGLImageKHR image, uint32_t width, uint32_t height) { | ||||
| 	struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)wlr_tex; | ||||
| 	struct wlr_gles2_texture *tex = gles2_get_texture(wlr_texture); | ||||
| 
 | ||||
| 	tex->image = image; | ||||
| 	tex->pixel_format = &external_pixel_format; | ||||
|  | @ -221,20 +243,21 @@ static bool gles2_texture_upload_eglimage(struct wlr_texture *wlr_tex, | |||
| 	tex->wlr_texture.width = width; | ||||
| 	tex->wlr_texture.height = height; | ||||
| 
 | ||||
| 	gles2_texture_ensure_texture(tex, GL_TEXTURE_2D); | ||||
| 
 | ||||
| 	GL_CALL(glActiveTexture(GL_TEXTURE0)); | ||||
| 	GL_CALL(glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex->tex_id)); | ||||
| 	GL_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, tex->image)); | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	gles2_texture_ensure(tex, GL_TEXTURE_2D); | ||||
| 	glActiveTexture(GL_TEXTURE0); | ||||
| 	glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex->tex_id); | ||||
| 	glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, tex->image); | ||||
| 	GLES2_DEBUG_POP; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static bool gles2_texture_upload_dmabuf(struct wlr_texture *_tex, | ||||
| static bool gles2_texture_upload_dmabuf(struct wlr_texture *wlr_texture, | ||||
| 		struct wl_resource *dmabuf_resource) { | ||||
| 	struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)_tex; | ||||
| 	struct wlr_dmabuf_buffer *dmabuf = wlr_dmabuf_buffer_from_buffer_resource( | ||||
| 		dmabuf_resource); | ||||
| 	struct wlr_gles2_texture *tex = gles2_get_texture(wlr_texture); | ||||
| 	struct wlr_dmabuf_buffer *dmabuf = | ||||
| 		wlr_dmabuf_buffer_from_buffer_resource(dmabuf_resource); | ||||
| 
 | ||||
| 	if (!tex->egl->egl_exts.dmabuf_import) { | ||||
| 		wlr_log(L_ERROR, "Want dmabuf but extension not present"); | ||||
|  | @ -249,17 +272,19 @@ static bool gles2_texture_upload_dmabuf(struct wlr_texture *_tex, | |||
| 	} | ||||
| 
 | ||||
| 	if (wlr_dmabuf_buffer_has_inverted_y(dmabuf)) { | ||||
| 		_tex->inverted_y = true; | ||||
| 		wlr_texture->inverted_y = true; | ||||
| 	} | ||||
| 
 | ||||
| 	GLenum target = GL_TEXTURE_2D; | ||||
| 	const struct pixel_format *pf = | ||||
| 		gl_format_for_wl_format(WL_SHM_FORMAT_ARGB8888); | ||||
| 	gles2_texture_ensure_texture(tex, target); | ||||
| 	GL_CALL(glBindTexture(target, tex->tex_id)); | ||||
| 	const struct gles2_pixel_format *pf = | ||||
| 		gles2_format_from_wl(WL_SHM_FORMAT_ARGB8888); | ||||
| 	GLES2_DEBUG_PUSH; | ||||
| 	gles2_texture_ensure(tex, target); | ||||
| 	glBindTexture(target, tex->tex_id); | ||||
| 	tex->image = wlr_egl_create_image_from_dmabuf(tex->egl, &dmabuf->attributes); | ||||
| 	GL_CALL(glActiveTexture(GL_TEXTURE0)); | ||||
| 	GL_CALL(glEGLImageTargetTexture2DOES(target, tex->image)); | ||||
| 	glActiveTexture(GL_TEXTURE0); | ||||
| 	glEGLImageTargetTexture2DOES(target, tex->image); | ||||
| 	GLES2_DEBUG_POP; | ||||
| 	tex->pixel_format = pf; | ||||
| 	tex->wlr_texture.valid = true; | ||||
| 	return true; | ||||
|  | @ -271,15 +296,15 @@ static bool gles2_texture_get_dmabuf_size(struct wlr_texture *texture, struct | |||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	struct wlr_dmabuf_buffer *dmabuf = wlr_dmabuf_buffer_from_buffer_resource( | ||||
| 		resource); | ||||
| 	struct wlr_dmabuf_buffer *dmabuf = | ||||
| 		wlr_dmabuf_buffer_from_buffer_resource(resource); | ||||
| 	*width = dmabuf->attributes.width; | ||||
| 	*height = dmabuf->attributes.height; | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| static void gles2_texture_get_buffer_size(struct wlr_texture *texture, struct | ||||
| 		wl_resource *resource, int *width, int *height) { | ||||
| static void gles2_texture_get_buffer_size(struct wlr_texture *texture, | ||||
| 		struct wl_resource *resource, int *width, int *height) { | ||||
| 	struct wl_shm_buffer *buffer = wl_shm_buffer_get(resource); | ||||
| 	if (!buffer) { | ||||
| 		struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)texture; | ||||
|  | @ -288,14 +313,13 @@ static void gles2_texture_get_buffer_size(struct wlr_texture *texture, struct | |||
| 		} | ||||
| 		if (!wlr_egl_query_buffer(tex->egl, resource, EGL_WIDTH, | ||||
| 				(EGLint*)width)) { | ||||
| 			if (!gles2_texture_get_dmabuf_size(texture, resource, | ||||
| 					width, height)) { | ||||
| 			if (!gles2_texture_get_dmabuf_size(texture, resource, width, | ||||
| 					height)) { | ||||
| 				wlr_log(L_ERROR, "could not get size of the buffer"); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 		wlr_egl_query_buffer(tex->egl, resource, EGL_HEIGHT, | ||||
| 			(EGLint*)height); | ||||
| 		wlr_egl_query_buffer(tex->egl, resource, EGL_HEIGHT, (EGLint*)height); | ||||
| 
 | ||||
| 		return; | ||||
| 	} | ||||
|  | @ -304,20 +328,15 @@ static void gles2_texture_get_buffer_size(struct wlr_texture *texture, struct | |||
| 	*height = wl_shm_buffer_get_height(buffer); | ||||
| } | ||||
| 
 | ||||
| static void gles2_texture_bind(struct wlr_texture *_texture) { | ||||
| 	struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; | ||||
| static void gles2_texture_destroy(struct wlr_texture *wlr_texture) { | ||||
| 	struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); | ||||
| 
 | ||||
| 	GL_CALL(glBindTexture(texture->target, texture->tex_id)); | ||||
| 	GL_CALL(glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR)); | ||||
| 	GL_CALL(glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR)); | ||||
| 	GL_CALL(glUseProgram(*texture->pixel_format->shader)); | ||||
| } | ||||
| 
 | ||||
| static void gles2_texture_destroy(struct wlr_texture *_texture) { | ||||
| 	struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture; | ||||
| 	wlr_signal_emit_safe(&texture->wlr_texture.destroy_signal, &texture->wlr_texture); | ||||
| 	wlr_signal_emit_safe(&texture->wlr_texture.destroy_signal, | ||||
| 		&texture->wlr_texture); | ||||
| 	if (texture->tex_id) { | ||||
| 		GL_CALL(glDeleteTextures(1, &texture->tex_id)); | ||||
| 		GLES2_DEBUG_PUSH; | ||||
| 		glDeleteTextures(1, &texture->tex_id); | ||||
| 		GLES2_DEBUG_POP; | ||||
| 	} | ||||
| 
 | ||||
| 	if (texture->image) { | ||||
|  | @ -327,7 +346,7 @@ static void gles2_texture_destroy(struct wlr_texture *_texture) { | |||
| 	free(texture); | ||||
| } | ||||
| 
 | ||||
| static struct wlr_texture_impl wlr_texture_impl = { | ||||
| static const struct wlr_texture_impl texture_impl = { | ||||
| 	.upload_pixels = gles2_texture_upload_pixels, | ||||
| 	.update_pixels = gles2_texture_update_pixels, | ||||
| 	.upload_shm = gles2_texture_upload_shm, | ||||
|  | @ -336,7 +355,6 @@ static struct wlr_texture_impl wlr_texture_impl = { | |||
| 	.upload_dmabuf = gles2_texture_upload_dmabuf, | ||||
| 	.upload_eglimage = gles2_texture_upload_eglimage, | ||||
| 	.get_buffer_size = gles2_texture_get_buffer_size, | ||||
| 	.bind = gles2_texture_bind, | ||||
| 	.destroy = gles2_texture_destroy, | ||||
| }; | ||||
| 
 | ||||
|  | @ -345,7 +363,7 @@ struct wlr_texture *gles2_texture_create(struct wlr_egl *egl) { | |||
| 	if (!(texture = calloc(1, sizeof(struct wlr_gles2_texture)))) { | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	wlr_texture_init(&texture->wlr_texture, &wlr_texture_impl); | ||||
| 	wlr_texture_init(&texture->wlr_texture, &texture_impl); | ||||
| 	texture->egl = egl; | ||||
| 	return &texture->wlr_texture; | ||||
| } | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ | |||
| #include <wlr/types/wlr_matrix.h> | ||||
| 
 | ||||
| void wlr_renderer_init(struct wlr_renderer *renderer, | ||||
| 		struct wlr_renderer_impl *impl) { | ||||
| 		const struct wlr_renderer_impl *impl) { | ||||
| 	renderer->impl = impl; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ | |||
| #include <wlr/render/wlr_texture.h> | ||||
| 
 | ||||
| void wlr_texture_init(struct wlr_texture *texture, | ||||
| 		struct wlr_texture_impl *impl) { | ||||
| 		const struct wlr_texture_impl *impl) { | ||||
| 	texture->impl = impl; | ||||
| 	wl_signal_init(&texture->destroy_signal); | ||||
| } | ||||
|  | @ -17,10 +17,6 @@ void wlr_texture_destroy(struct wlr_texture *texture) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| void wlr_texture_bind(struct wlr_texture *texture) { | ||||
| 	texture->impl->bind(texture); | ||||
| } | ||||
| 
 | ||||
| bool wlr_texture_upload_pixels(struct wlr_texture *texture, uint32_t format, | ||||
| 		int stride, int width, int height, const unsigned char *pixels) { | ||||
| 	return texture->impl->upload_pixels(texture, format, stride, | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 emersion
						emersion