Implement shm buffer surface attach interface

Implement surface_attach method. This is called when a client attaches an shm
buffer with wl_surface_attach().

Implement the GLES2 interface for attaching shm buffers. This creates an opengl
texture with the shm buffer contents for the surface.

This commit also includes some working code to render the surfaces onto the
screen for demonstration purposes.
This commit is contained in:
Tony Crisci 2017-08-03 14:20:51 -04:00
parent 555914a13b
commit 6610aa7ca7
4 changed files with 49 additions and 4 deletions

View File

@ -7,6 +7,7 @@ struct wl_compositor_state {
struct wl_global *wl_global; struct wl_global *wl_global;
struct wl_list wl_resources; struct wl_list wl_resources;
struct wlr_renderer *renderer; struct wlr_renderer *renderer;
struct wl_list surfaces;
}; };
void wl_compositor_init(struct wl_display *display, void wl_compositor_init(struct wl_display *display,

View File

@ -28,7 +28,18 @@ void handle_output_frame(struct output_state *output, struct timespec *ts) {
wlr_output_make_current(wlr_output); wlr_output_make_current(wlr_output);
wlr_renderer_begin(sample->renderer, wlr_output); wlr_renderer_begin(sample->renderer, wlr_output);
// TODO: render surfaces
struct wl_resource *_res;
float matrix[16];
wl_list_for_each(_res, &sample->compositor.surfaces, link) {
struct wlr_surface *surface = wl_resource_get_user_data(_res);
if (surface->valid) {
wlr_surface_get_matrix(surface, &matrix,
&wlr_output->transform_matrix, 200, 200);
wlr_render_with_matrix(sample->renderer, surface, &matrix);
}
}
wlr_renderer_end(sample->renderer); wlr_renderer_end(sample->renderer);
wlr_output_swap_buffers(wlr_output); wlr_output_swap_buffers(wlr_output);
} }

View File

@ -10,7 +10,10 @@ static void surface_destroy(struct wl_client *client, struct wl_resource *resour
static void surface_attach(struct wl_client *client, static void surface_attach(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *resource,
struct wl_resource *buffer_resource, int32_t sx, int32_t sy) { struct wl_resource *buffer_resource, int32_t sx, int32_t sy) {
wlr_log(L_DEBUG, "TODO: surface attach"); struct wlr_surface *surface = wl_resource_get_user_data(resource);
struct wl_shm_buffer *buffer = wl_shm_buffer_get(buffer_resource);
uint32_t format = wl_shm_buffer_get_format(buffer);
wlr_surface_attach_shm(surface, format, buffer);
} }
static void surface_damage(struct wl_client *client, static void surface_damage(struct wl_client *client,
@ -87,7 +90,7 @@ static void wl_compositor_create_surface(struct wl_client *client,
wl_resource_set_implementation(surface_resource, &surface_interface, wl_resource_set_implementation(surface_resource, &surface_interface,
surface, destroy_surface); surface, destroy_surface);
wl_resource_set_user_data(surface_resource, surface); wl_resource_set_user_data(surface_resource, surface);
wl_list_insert(&state->surfaces, wl_resource_get_link(surface_resource));
} }
static void wl_compositor_create_region(struct wl_client *client, static void wl_compositor_create_region(struct wl_client *client,
@ -135,4 +138,5 @@ void wl_compositor_init(struct wl_display *display,
state->wl_global = wl_global; state->wl_global = wl_global;
state->renderer = renderer; state->renderer = renderer;
wl_list_init(&state->wl_resources); wl_list_init(&state->wl_resources);
wl_list_init(&state->surfaces);
} }

View File

@ -34,6 +34,35 @@ static bool gles2_surface_attach_pixels(struct wlr_surface_state *surface,
return true; return true;
} }
static bool gles2_surface_attach_shm(struct wlr_surface_state *surface,
uint32_t format, struct wl_shm_buffer *buffer) {
const struct pixel_format *fmt = gl_format_for_wl_format(format);
if (!fmt || !fmt->gl_format) {
wlr_log(L_ERROR, "No supported pixel format for this surface");
return false;
}
wl_shm_buffer_begin_access(buffer);
uint8_t *pixels = wl_shm_buffer_get_data(buffer);
int width = wl_shm_buffer_get_width(buffer);
int height = wl_shm_buffer_get_height(buffer);
int pitch = wl_shm_buffer_get_stride(buffer) / (fmt->bpp / 8);
surface->wlr_surface->width = width;
surface->wlr_surface->height = height;
surface->wlr_surface->format = format;
surface->pixel_format = fmt;
GL_CALL(glActiveTexture(GL_TEXTURE0));
GL_CALL(glGenTextures(1, &surface->tex_id));
GL_CALL(glBindTexture(GL_TEXTURE_2D, surface->tex_id));
GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch));
GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0,
fmt->gl_format, fmt->gl_type, pixels));
surface->wlr_surface->valid = true;
wl_shm_buffer_end_access(buffer);
return true;
}
static void gles2_surface_get_matrix(struct wlr_surface_state *surface, static void gles2_surface_get_matrix(struct wlr_surface_state *surface,
float (*matrix)[16], const float (*projection)[16], int x, int y) { float (*matrix)[16], const float (*projection)[16], int x, int y) {
struct wlr_surface *_surface = surface->wlr_surface; struct wlr_surface *_surface = surface->wlr_surface;
@ -61,7 +90,7 @@ static void gles2_surface_destroy(struct wlr_surface_state *surface) {
static struct wlr_surface_impl wlr_surface_impl = { static struct wlr_surface_impl wlr_surface_impl = {
.attach_pixels = gles2_surface_attach_pixels, .attach_pixels = gles2_surface_attach_pixels,
// .attach_shm = TODO .attach_shm = gles2_surface_attach_shm,
.get_matrix = gles2_surface_get_matrix, .get_matrix = gles2_surface_get_matrix,
.bind = gles2_surface_bind, .bind = gles2_surface_bind,
.destroy = gles2_surface_destroy, .destroy = gles2_surface_destroy,