diff options
| -rw-r--r-- | backend/drm/drm.c | 25 | ||||
| -rw-r--r-- | backend/drm/renderer.c | 23 | ||||
| -rw-r--r-- | backend/headless/output.c | 14 | ||||
| -rw-r--r-- | backend/wayland/output.c | 21 | ||||
| -rw-r--r-- | examples/output-layout.c | 2 | ||||
| -rw-r--r-- | examples/rotation.c | 2 | ||||
| -rw-r--r-- | examples/tablet.c | 2 | ||||
| -rw-r--r-- | examples/touch.c | 2 | ||||
| -rw-r--r-- | include/render/gles2.h | 45 | ||||
| -rw-r--r-- | include/wlr/render/interface.h | 13 | ||||
| -rw-r--r-- | include/wlr/render/wlr_renderer.h | 2 | ||||
| -rw-r--r-- | include/wlr/render/wlr_texture.h | 2 | ||||
| -rw-r--r-- | render/glapi.txt | 4 | ||||
| -rw-r--r-- | render/gles2/pixel_format.c | 25 | ||||
| -rw-r--r-- | render/gles2/renderer.c | 456 | ||||
| -rw-r--r-- | render/gles2/shaders.c | 148 | ||||
| -rw-r--r-- | render/gles2/texture.c | 224 | ||||
| -rw-r--r-- | render/wlr_renderer.c | 6 | ||||
| -rw-r--r-- | render/wlr_texture.c | 6 | ||||
| -rw-r--r-- | rootston/output.c | 2 | ||||
| -rw-r--r-- | wlroots.syms | 2 | 
21 files changed, 590 insertions, 436 deletions
diff --git a/backend/drm/drm.c b/backend/drm/drm.c index 344756f8..524e80bb 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -582,11 +582,8 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,  			return false;  		} -		// OpenGL will read the pixels out upside down, -		// so we need to flip the image vertically -		enum wl_output_transform transform = wlr_output_transform_compose( -			wlr_output_transform_invert(output->transform), -			WL_OUTPUT_TRANSFORM_FLIPPED_180); +		enum wl_output_transform transform = +			wlr_output_transform_invert(output->transform);  		wlr_matrix_projection(plane->matrix, plane->surf.width,  			plane->surf.height, transform); @@ -643,18 +640,14 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,  		wlr_texture_upload_pixels(plane->wlr_tex, WL_SHM_FORMAT_ARGB8888,  			stride, width, height, buf); -		glViewport(0, 0, plane->surf.width, plane->surf.height); -		glClearColor(0.0, 0.0, 0.0, 0.0); -		glClear(GL_COLOR_BUFFER_BIT); +		struct wlr_renderer *rend = plane->surf.renderer->wlr_rend; +		wlr_renderer_begin(rend, plane->surf.width, plane->surf.height); +		wlr_renderer_clear(rend, (float[]){ 0.0, 0.0, 0.0, 0.0 }); +		wlr_render_texture(rend, plane->wlr_tex, plane->matrix, 0, 0, 1.0f); +		wlr_renderer_end(rend); -		wlr_render_texture(plane->surf.renderer->wlr_rend, plane->wlr_tex, -			plane->matrix, 0, 0, 1.0f); - -		glFinish(); -		glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, bo_stride); -		glReadPixels(0, 0, plane->surf.width, plane->surf.height, GL_BGRA_EXT, -			GL_UNSIGNED_BYTE, bo_data); -		glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0); +		wlr_renderer_read_pixels(rend, WL_SHM_FORMAT_ARGB8888, bo_stride, +			plane->surf.width, plane->surf.height, 0, 0, 0, 0, bo_data);  		wlr_drm_surface_swap_buffers(&plane->surf, NULL); diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c index 528cd26c..b2998b5f 100644 --- a/backend/drm/renderer.c +++ b/backend/drm/renderer.c @@ -2,7 +2,6 @@  #include <EGL/egl.h>  #include <EGL/eglext.h>  #include <gbm.h> -#include <GLES2/gl2.h>  #include <stdbool.h>  #include <stdlib.h>  #include <unistd.h> @@ -107,9 +106,6 @@ void wlr_drm_surface_finish(struct wlr_drm_surface *surf) {  		return;  	} -	eglMakeCurrent(surf->renderer->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE, -		EGL_NO_CONTEXT); -  	if (surf->front) {  		gbm_surface_release_buffer(surf->gbm, surf->front);  	} @@ -151,9 +147,10 @@ struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf) {  	}  	wlr_drm_surface_make_current(surf, NULL); -	glViewport(0, 0, surf->width, surf->height); -	glClearColor(0.0, 0.0, 0.0, 1.0); -	glClear(GL_COLOR_BUFFER_BIT); +	struct wlr_renderer *renderer = surf->renderer->wlr_rend; +	wlr_renderer_begin(renderer, surf->width, surf->height); +	wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 1.0 }); +	wlr_renderer_end(renderer);  	return wlr_drm_surface_swap_buffers(surf, NULL);  } @@ -185,6 +182,8 @@ static struct wlr_texture *get_tex_for_bo(struct wlr_drm_renderer *renderer,  		return tex->tex;  	} +	// TODO: use wlr_texture_upload_dmabuf instead +  	tex = malloc(sizeof(*tex));  	if (!tex) {  		wlr_log_errno(L_ERROR, "Allocation failed"); @@ -230,14 +229,14 @@ struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest,  	struct wlr_texture *tex = get_tex_for_bo(dest->renderer, src);  	assert(tex); -	static const float color[] = {0.0, 0.0, 0.0, 1.0}; -  	float mat[9];  	wlr_matrix_projection(mat, 1, 1, WL_OUTPUT_TRANSFORM_FLIPPED_180); -	glViewport(0, 0, dest->width, dest->height); -	wlr_renderer_clear(dest->renderer->wlr_rend, color); -	wlr_render_texture_with_matrix(dest->renderer->wlr_rend, tex, mat, 1.0f); +	struct wlr_renderer *renderer = dest->renderer->wlr_rend; +	wlr_renderer_begin(renderer, dest->width, dest->height); +	wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 1.0 }); +	wlr_render_texture_with_matrix(renderer, tex, mat, 1.0f); +	wlr_renderer_end(renderer);  	return wlr_drm_surface_swap_buffers(dest, NULL);  } diff --git a/backend/headless/output.c b/backend/headless/output.c index fc275eaf..a13ed22c 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -1,8 +1,8 @@  #include <EGL/egl.h>  #include <EGL/eglext.h> -#include <GLES2/gl2.h>  #include <stdlib.h>  #include <wlr/interfaces/wlr_output.h> +#include <wlr/render/wlr_renderer.h>  #include <wlr/util/log.h>  #include "backend/headless.h"  #include "util/signal.h" @@ -120,16 +120,14 @@ struct wlr_output *wlr_headless_add_output(struct wlr_backend *wlr_backend,  	snprintf(wlr_output->name, sizeof(wlr_output->name), "HEADLESS-%d",  		wl_list_length(&backend->outputs) + 1); -	if (!eglMakeCurrent(output->backend->egl.display, -			output->egl_surface, output->egl_surface, -			output->backend->egl.context)) { -		wlr_log(L_ERROR, "eglMakeCurrent failed"); +	if (!wlr_egl_make_current(&output->backend->egl, output->egl_surface, +			NULL)) {  		goto error;  	} -	glViewport(0, 0, wlr_output->width, wlr_output->height); -	glClearColor(1.0, 1.0, 1.0, 1.0); -	glClear(GL_COLOR_BUFFER_BIT); +	wlr_renderer_begin(backend->renderer, wlr_output->width, wlr_output->height); +	wlr_renderer_clear(backend->renderer, (float[]){ 1.0, 1.0, 1.0, 1.0 }); +	wlr_renderer_end(backend->renderer);  	struct wl_event_loop *ev = wl_display_get_event_loop(backend->display);  	output->frame_timer = wl_event_loop_add_timer(ev, signal_frame, output); diff --git a/backend/wayland/output.c b/backend/wayland/output.c index 6becceb7..d528c888 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -1,5 +1,4 @@  #include <assert.h> -#include <GLES2/gl2.h>  #include <stdint.h>  #include <stdio.h>  #include <stdlib.h> @@ -9,6 +8,7 @@  #include <unistd.h>  #include <wayland-client.h>  #include <wlr/interfaces/wlr_output.h> +#include <wlr/render/wlr_renderer.h>  #include <wlr/util/log.h>  #include "backend/wayland.h"  #include "util/signal.h" @@ -313,27 +313,26 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *_backend) {  	output->egl_window = wl_egl_window_create(output->surface,  			wlr_output->width, wlr_output->height); -	output->egl_surface = wlr_egl_create_surface(&backend->egl, output->egl_window); +	output->egl_surface = wlr_egl_create_surface(&backend->egl, +		output->egl_window);  	wl_display_roundtrip(output->backend->remote_display);  	// start rendering loop per callbacks by rendering first frame -	if (!eglMakeCurrent(output->backend->egl.display, -		output->egl_surface, output->egl_surface, -		output->backend->egl.context)) { -		wlr_log(L_ERROR, "eglMakeCurrent failed"); +	if (!wlr_egl_make_current(&output->backend->egl, output->egl_surface, +			NULL)) {  		goto error;  	} -	glViewport(0, 0, wlr_output->width, wlr_output->height); -	glClearColor(1.0, 1.0, 1.0, 1.0); -	glClear(GL_COLOR_BUFFER_BIT); +	wlr_renderer_begin(backend->renderer, wlr_output->width, wlr_output->height); +	wlr_renderer_clear(backend->renderer, (float[]){ 1.0, 1.0, 1.0, 1.0 }); +	wlr_renderer_end(backend->renderer);  	output->frame_callback = wl_surface_frame(output->surface);  	wl_callback_add_listener(output->frame_callback, &frame_listener, output); -	if (!eglSwapBuffers(output->backend->egl.display, output->egl_surface)) { -		wlr_log(L_ERROR, "eglSwapBuffers failed"); +	if (!wlr_egl_swap_buffers(&output->backend->egl, output->egl_surface, +			NULL)) {  		goto error;  	} diff --git a/examples/output-layout.c b/examples/output-layout.c index de134a71..45d896b0 100644 --- a/examples/output-layout.c +++ b/examples/output-layout.c @@ -101,7 +101,7 @@ static void handle_output_frame(struct output_state *output,  	struct wlr_output *wlr_output = output->output;  	wlr_output_make_current(wlr_output, NULL); -	wlr_renderer_begin(sample->renderer, wlr_output); +	wlr_renderer_begin(sample->renderer, wlr_output->width, wlr_output->height);  	wlr_renderer_clear(sample->renderer, (float[]){0.25f, 0.25f, 0.25f, 1});  	animate_cat(sample, output->output); diff --git a/examples/rotation.c b/examples/rotation.c index 7f50b620..cbff09a1 100644 --- a/examples/rotation.c +++ b/examples/rotation.c @@ -43,7 +43,7 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts  	wlr_output_effective_resolution(wlr_output, &width, &height);  	wlr_output_make_current(wlr_output, NULL); -	wlr_renderer_begin(sample->renderer, wlr_output); +	wlr_renderer_begin(sample->renderer, wlr_output->width, wlr_output->height);  	wlr_renderer_clear(sample->renderer, (float[]){0.25f, 0.25f, 0.25f, 1});  	for (int y = -128 + (int)odata->y_offs; y < height; y += 128) { diff --git a/examples/tablet.c b/examples/tablet.c index 1b995003..65c559cb 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -46,7 +46,7 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts  	wlr_output_effective_resolution(wlr_output, &width, &height);  	wlr_output_make_current(wlr_output, NULL); -	wlr_renderer_begin(sample->renderer, wlr_output); +	wlr_renderer_begin(sample->renderer, wlr_output->width, wlr_output->height);  	wlr_renderer_clear(sample->renderer, (float[]){0.25f, 0.25f, 0.25f, 1});  	float matrix[9]; diff --git a/examples/touch.c b/examples/touch.c index 0968e82a..f9c496cf 100644 --- a/examples/touch.c +++ b/examples/touch.c @@ -42,7 +42,7 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts  	wlr_output_effective_resolution(wlr_output, &width, &height);  	wlr_output_make_current(wlr_output, NULL); -	wlr_renderer_begin(sample->renderer, wlr_output); +	wlr_renderer_begin(sample->renderer, wlr_output->width, wlr_output->height);  	wlr_renderer_clear(sample->renderer, (float[]){0.25f, 0.25f, 0.25f, 1});  	struct touch_point *p; diff --git a/include/render/gles2.h b/include/render/gles2.h index 0a4fb49f..43a8d648 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -17,17 +17,25 @@  extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; -struct pixel_format { +struct gles2_pixel_format {  	uint32_t wl_format;  	GLint gl_format, gl_type;  	int depth, bpp; -	GLuint *shader; +	bool has_alpha;  };  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 +43,20 @@ 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); +const enum wl_shm_format *gles2_formats(size_t *len);  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 diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index f0307230..7f25c0ff 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -14,11 +14,12 @@  struct wlr_renderer_impl;  struct wlr_renderer { -	struct wlr_renderer_impl *impl; +	const struct wlr_renderer_impl *impl;  };  struct wlr_renderer_impl { -	void (*begin)(struct wlr_renderer *renderer, struct wlr_output *output); +	void (*begin)(struct wlr_renderer *renderer, uint32_t width, +		uint32_t height);  	void (*end)(struct wlr_renderer *renderer);  	void (*clear)(struct wlr_renderer *renderer, const float color[static 4]);  	void (*scissor)(struct wlr_renderer *renderer, struct wlr_box *box); @@ -44,7 +45,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,14 +66,12 @@ 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); +	struct wl_resource *resource, int *width, int *height);  #endif diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h index d5f3cf70..6f0d2ecc 100644 --- a/include/wlr/render/wlr_renderer.h +++ b/include/wlr/render/wlr_renderer.h @@ -12,7 +12,7 @@ struct wlr_output;  struct wlr_renderer; -void wlr_renderer_begin(struct wlr_renderer *r, struct wlr_output *output); +void wlr_renderer_begin(struct wlr_renderer *r, int width, int height);  void wlr_renderer_end(struct wlr_renderer *r);  void wlr_renderer_clear(struct wlr_renderer *r, const float color[static 4]);  /** diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 49aa93d7..095097e6 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -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; diff --git a/render/glapi.txt b/render/glapi.txt index 2077d1c3..a8e4aaba 100644 --- a/render/glapi.txt +++ b/render/glapi.txt @@ -11,3 +11,7 @@ eglCreatePlatformWindowSurfaceEXT  -eglQueryDmaBufFormatsEXT  -eglQueryDmaBufModifiersEXT  -eglDebugMessageControlKHR +-glDebugMessageCallbackKHR +-glDebugMessageControlKHR +-glPopDebugGroupKHR +-glPushDebugGroupKHR diff --git a/render/gles2/pixel_format.c b/render/gles2/pixel_format.c index a544077b..89ba762f 100644 --- a/render/gles2/pixel_format.c +++ b/render/gles2/pixel_format.c @@ -6,14 +6,14 @@  * 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[] = { +static const 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 +		.has_alpha = true,  	},  	{  		.wl_format = WL_SHM_FORMAT_XRGB8888, @@ -21,7 +21,7 @@ struct pixel_format formats[] = {  		.bpp = 32,  		.gl_format = GL_BGRA_EXT,  		.gl_type = GL_UNSIGNED_BYTE, -		.shader = &shaders.rgbx +		.has_alpha = false,  	},  	{  		.wl_format = WL_SHM_FORMAT_XBGR8888, @@ -29,7 +29,7 @@ struct pixel_format formats[] = {  		.bpp = 32,  		.gl_format = GL_RGBA,  		.gl_type = GL_UNSIGNED_BYTE, -		.shader = &shaders.rgbx +		.has_alpha = false,  	},  	{  		.wl_format = WL_SHM_FORMAT_ABGR8888, @@ -37,12 +37,20 @@ struct pixel_format formats[] = {  		.bpp = 32,  		.gl_format = GL_RGBA,  		.gl_type = GL_UNSIGNED_BYTE, -		.shader = &shaders.rgba +		.has_alpha = true,  	},  }; + +static const enum wl_shm_format wl_formats[] = { +	WL_SHM_FORMAT_ARGB8888, +	WL_SHM_FORMAT_XRGB8888, +	WL_SHM_FORMAT_ABGR8888, +	WL_SHM_FORMAT_XBGR8888, +}; +  // 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]; @@ -50,3 +58,8 @@ const struct pixel_format *gl_format_for_wl_format(enum wl_shm_format fmt) {  	}  	return NULL;  } + +const enum wl_shm_format *gles2_formats(size_t *len) { +	*len = sizeof(wl_formats) / sizeof(wl_formats[0]); +	return wl_formats; +} diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index f525869d..9403c0ed 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -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 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 const struct wlr_renderer_impl renderer_impl; -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 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 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 gles2_begin(struct wlr_renderer *wlr_renderer, uint32_t width, +		uint32_t height) { +	gles2_get_renderer(wlr_renderer); -static void init_globals() { -	init_default_shaders(); -} +	GLES2_DEBUG_PUSH; -static void wlr_gles2_begin(struct wlr_renderer *wlr_renderer, -		struct wlr_output *output) { -	GL_CALL(glViewport(0, 0, output->width, output->height)); +	glViewport(0, 0, width, 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,97 +95,117 @@ 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->has_alpha) { +		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( -		struct wlr_renderer *renderer, size_t *len) { -	static enum wl_shm_format formats[] = { -		WL_SHM_FORMAT_ARGB8888, -		WL_SHM_FORMAT_XRGB8888, -		WL_SHM_FORMAT_ABGR8888, -		WL_SHM_FORMAT_XBGR8888, -	}; -	*len = sizeof(formats) / sizeof(formats[0]); -	return formats; +static const enum wl_shm_format *gles2_renderer_formats( +		struct wlr_renderer *wlr_renderer, size_t *len) { +	return gles2_formats(len);  } -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 +217,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 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 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 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_renderer_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;  } diff --git a/render/gles2/shaders.c b/render/gles2/shaders.c index 30e12e4c..ba3bd971 100644 --- a/render/gles2/shaders.c +++ b/render/gles2/shaders.c @@ -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"; diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 8da40032..766c0b15 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -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;  	} @@ -160,9 +177,9 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex,  	}  	wlr_egl_query_buffer(tex->egl, buf, EGL_WIDTH, -			(EGLint*)&tex->wlr_texture.width); +		(EGLint*)&tex->wlr_texture.width);  	wlr_egl_query_buffer(tex->egl, buf, EGL_HEIGHT, -			(EGLint*)&tex->wlr_texture.height); +		(EGLint*)&tex->wlr_texture.height);  	EGLint inverted_y;  	if (wlr_egl_query_buffer(tex->egl, buf, EGL_WAYLAND_Y_INVERTED_WL, @@ -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; - -	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 *wlr_texture) { +	struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); -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;  } diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 21a7901a..622aa1dd 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -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;  } @@ -17,8 +17,8 @@ void wlr_renderer_destroy(struct wlr_renderer *r) {  	}  } -void wlr_renderer_begin(struct wlr_renderer *r, struct wlr_output *o) { -	r->impl->begin(r, o); +void wlr_renderer_begin(struct wlr_renderer *r, int width, int height) { +	r->impl->begin(r, width, height);  }  void wlr_renderer_end(struct wlr_renderer *r) { diff --git a/render/wlr_texture.c b/render/wlr_texture.c index a5d0abde..33c91822 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -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, diff --git a/rootston/output.c b/rootston/output.c index 22c0d7ed..1284c928 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -479,7 +479,7 @@ static void render_output(struct roots_output *output) {  		goto damage_finish;  	} -	wlr_renderer_begin(renderer, wlr_output); +	wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);  	if (!pixman_region32_not_empty(&damage)) {  		// Output isn't damaged but needs buffer swap diff --git a/wlroots.syms b/wlroots.syms index 3f45e045..cb030a6d 100644 --- a/wlroots.syms +++ b/wlroots.syms @@ -15,8 +15,8 @@ WLROOTS_0_0_0 {          wlr_drm_get_connector_props;          wlr_drm_get_crtc_props;          wlr_drm_get_plane_props; -        wlr_drm_get_prop;          wlr_drm_get_prop_blob; +        wlr_drm_get_prop;          wlr_drm_plane_surfaces_init;          wlr_drm_renderer_finish;          wlr_drm_renderer_init;  | 
