gl-renderer: Split buffer state away from surface state

gl_surface_state has a bunch of members which are tied to the input
buffer, rather than the surface per se.

Split them out into a separate gl_buffer_state member as a first step
towards sanitising its use and lifetime.

Signed-off-by: Daniel Stone <daniels@collabora.com>
dev
Daniel Stone 3 years ago
parent 0c65b23848
commit 72fc647a96
  1. 328
      libweston/renderer-gl/gl-renderer.c

@ -168,11 +168,9 @@ struct yuv_format_descriptor {
struct yuv_plane_descriptor plane[4]; struct yuv_plane_descriptor plane[4];
}; };
struct gl_surface_state { struct gl_buffer_state {
GLfloat color[4]; GLfloat color[4];
GLuint textures[3];
int num_textures;
bool needs_full_upload; bool needs_full_upload;
pixman_region32_t texture_damage; pixman_region32_t texture_damage;
@ -186,8 +184,6 @@ struct gl_surface_state {
int num_images; int num_images;
enum gl_shader_texture_variant shader_variant; enum gl_shader_texture_variant shader_variant;
struct weston_buffer_reference buffer_ref;
struct weston_buffer_release_reference buffer_release_ref;
enum buffer_type buffer_type; enum buffer_type buffer_type;
int pitch; /* in pixels */ int pitch; /* in pixels */
int height; /* in pixels */ int height; /* in pixels */
@ -198,13 +194,25 @@ struct gl_surface_state {
int offset[3]; /* offset per plane */ int offset[3]; /* offset per plane */
int hsub[3]; /* horizontal subsampling per plane */ int hsub[3]; /* horizontal subsampling per plane */
int vsub[3]; /* vertical subsampling per plane */ int vsub[3]; /* vertical subsampling per plane */
};
struct gl_surface_state {
struct weston_surface *surface; struct weston_surface *surface;
struct gl_buffer_state buffer;
/* These buffer references should really be attached to paint nodes
* rather than either buffer or surface state */
struct weston_buffer_reference buffer_ref;
struct weston_buffer_release_reference buffer_release_ref;
/* Whether this surface was used in the current output repaint. /* Whether this surface was used in the current output repaint.
Used only in the context of a gl_renderer_repaint_output call. */ Used only in the context of a gl_renderer_repaint_output call. */
bool used_in_output_repaint; bool used_in_output_repaint;
GLuint textures[3];
int num_textures;
struct wl_listener surface_destroy_listener; struct wl_listener surface_destroy_listener;
struct wl_listener renderer_destroy_listener; struct wl_listener renderer_destroy_listener;
}; };
@ -568,6 +576,7 @@ texture_region(struct weston_view *ev,
pixman_region32_t *surf_region) pixman_region32_t *surf_region)
{ {
struct gl_surface_state *gs = get_surface_state(ev->surface); struct gl_surface_state *gs = get_surface_state(ev->surface);
struct gl_buffer_state *gb = &gs->buffer;
struct weston_compositor *ec = ev->surface->compositor; struct weston_compositor *ec = ev->surface->compositor;
struct gl_renderer *gr = get_renderer(ec); struct gl_renderer *gr = get_renderer(ec);
GLfloat *v, inv_width, inv_height; GLfloat *v, inv_width, inv_height;
@ -593,8 +602,8 @@ texture_region(struct weston_view *ev,
v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 4 * sizeof *v); v = wl_array_add(&gr->vertices, nrects * nsurf * 8 * 4 * sizeof *v);
vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt); vtxcnt = wl_array_add(&gr->vtxcnt, nrects * nsurf * sizeof *vtxcnt);
inv_width = 1.0 / gs->pitch; inv_width = 1.0 / gb->pitch;
inv_height = 1.0 / gs->height; inv_height = 1.0 / gb->height;
for (i = 0; i < nrects; i++) { for (i = 0; i < nrects; i++) {
pixman_box32_t *rect = &rects[i]; pixman_box32_t *rect = &rects[i];
@ -634,10 +643,10 @@ texture_region(struct weston_view *ev,
sx, sy, sx, sy,
&bx, &by); &bx, &by);
*(v++) = bx * inv_width; *(v++) = bx * inv_width;
if (gs->y_inverted) { if (gb->y_inverted) {
*(v++) = by * inv_height; *(v++) = by * inv_height;
} else { } else {
*(v++) = (gs->height - by) * inv_height; *(v++) = (gb->height - by) * inv_height;
} }
} }
@ -967,6 +976,7 @@ maybe_censor_override(struct gl_shader_config *sconf,
struct weston_view *ev) struct weston_view *ev)
{ {
struct gl_surface_state *gs = get_surface_state(ev->surface); struct gl_surface_state *gs = get_surface_state(ev->surface);
struct gl_buffer_state *gb = &gs->buffer;
bool recording_censor = bool recording_censor =
(output->disable_planes > 0) && (output->disable_planes > 0) &&
(ev->surface->desired_protection > WESTON_HDCP_DISABLE); (ev->surface->desired_protection > WESTON_HDCP_DISABLE);
@ -974,7 +984,7 @@ maybe_censor_override(struct gl_shader_config *sconf,
bool unprotected_censor = bool unprotected_censor =
(ev->surface->desired_protection > output->current_protection); (ev->surface->desired_protection > output->current_protection);
if (gs->direct_display) { if (gb->direct_display) {
censor_override(sconf, output); censor_override(sconf, output);
return; return;
} }
@ -993,14 +1003,15 @@ static void
gl_shader_config_set_input_textures(struct gl_shader_config *sconf, gl_shader_config_set_input_textures(struct gl_shader_config *sconf,
struct gl_surface_state *gs) struct gl_surface_state *gs)
{ {
struct gl_buffer_state *gb = &gs->buffer;
int i; int i;
sconf->req.variant = gs->shader_variant; sconf->req.variant = gb->shader_variant;
sconf->req.input_is_premult = sconf->req.input_is_premult =
gl_shader_texture_variant_can_be_premult(gs->shader_variant); gl_shader_texture_variant_can_be_premult(gb->shader_variant);
for (i = 0; i < 4; i++) for (i = 0; i < 4; i++)
sconf->unicolor[i] = gs->color[i]; sconf->unicolor[i] = gb->color[i];
assert(gs->num_textures <= GL_SHADER_INPUT_TEX_MAX); assert(gs->num_textures <= GL_SHADER_INPUT_TEX_MAX);
for (i = 0; i < gs->num_textures; i++) for (i = 0; i < gs->num_textures; i++)
@ -1042,6 +1053,7 @@ draw_paint_node(struct weston_paint_node *pnode,
{ {
struct gl_renderer *gr = get_renderer(pnode->surface->compositor); struct gl_renderer *gr = get_renderer(pnode->surface->compositor);
struct gl_surface_state *gs = get_surface_state(pnode->surface); struct gl_surface_state *gs = get_surface_state(pnode->surface);
struct gl_buffer_state *gb = &gs->buffer;
/* repaint bounding region in global coordinates: */ /* repaint bounding region in global coordinates: */
pixman_region32_t repaint; pixman_region32_t repaint;
/* opaque region in surface coordinates: */ /* opaque region in surface coordinates: */
@ -1054,7 +1066,7 @@ draw_paint_node(struct weston_paint_node *pnode,
/* In case of a runtime switch of renderers, we may not have received /* In case of a runtime switch of renderers, we may not have received
* an attach for this surface since the switch. In that case we don't * an attach for this surface since the switch. In that case we don't
* have a valid buffer or a proper shader set up so skip rendering. */ * have a valid buffer or a proper shader set up so skip rendering. */
if (gs->shader_variant == SHADER_VARIANT_NONE && !gs->direct_display) if (gb->shader_variant == SHADER_VARIANT_NONE && !gb->direct_display)
return; return;
pixman_region32_init(&repaint); pixman_region32_init(&repaint);
@ -1845,6 +1857,7 @@ gl_renderer_flush_damage(struct weston_surface *surface,
const struct weston_testsuite_quirks *quirks = const struct weston_testsuite_quirks *quirks =
&surface->compositor->test_data.test_quirks; &surface->compositor->test_data.test_quirks;
struct gl_surface_state *gs = get_surface_state(surface); struct gl_surface_state *gs = get_surface_state(surface);
struct gl_buffer_state *gb = &gs->buffer;
struct weston_view *view; struct weston_view *view;
bool texture_used; bool texture_used;
pixman_box32_t *rectangles; pixman_box32_t *rectangles;
@ -1853,8 +1866,8 @@ gl_renderer_flush_damage(struct weston_surface *surface,
assert(buffer); assert(buffer);
pixman_region32_union(&gs->texture_damage, pixman_region32_union(&gb->texture_damage,
&gs->texture_damage, &surface->damage); &gb->texture_damage, &surface->damage);
/* This can happen if a SHM wl_buffer gets destroyed before we flush /* This can happen if a SHM wl_buffer gets destroyed before we flush
* damage, because wayland-server just nukes the wl_shm_buffer from * damage, because wayland-server just nukes the wl_shm_buffer from
@ -1877,36 +1890,36 @@ gl_renderer_flush_damage(struct weston_surface *surface,
if (!texture_used) if (!texture_used)
return; return;
if (!pixman_region32_not_empty(&gs->texture_damage) && if (!pixman_region32_not_empty(&gb->texture_damage) &&
!gs->needs_full_upload) !gb->needs_full_upload)
goto done; goto done;
data = wl_shm_buffer_get_data(buffer->shm_buffer); data = wl_shm_buffer_get_data(buffer->shm_buffer);
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
if (gs->needs_full_upload || quirks->gl_force_full_upload) { if (gb->needs_full_upload || quirks->gl_force_full_upload) {
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0); glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0); glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
wl_shm_buffer_begin_access(buffer->shm_buffer); wl_shm_buffer_begin_access(buffer->shm_buffer);
for (j = 0; j < gs->num_textures; j++) { for (j = 0; j < gs->num_textures; j++) {
glBindTexture(GL_TEXTURE_2D, gs->textures[j]); glBindTexture(GL_TEXTURE_2D, gs->textures[j]);
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT,
gs->pitch / gs->hsub[j]); gb->pitch / gb->hsub[j]);
glTexImage2D(GL_TEXTURE_2D, 0, glTexImage2D(GL_TEXTURE_2D, 0,
gs->gl_format[j], gb->gl_format[j],
gs->pitch / gs->hsub[j], gb->pitch / gb->hsub[j],
buffer->height / gs->vsub[j], buffer->height / gb->vsub[j],
0, 0,
gl_format_from_internal(gs->gl_format[j]), gl_format_from_internal(gb->gl_format[j]),
gs->gl_pixel_type, gb->gl_pixel_type,
data + gs->offset[j]); data + gb->offset[j]);
} }
wl_shm_buffer_end_access(buffer->shm_buffer); wl_shm_buffer_end_access(buffer->shm_buffer);
goto done; goto done;
} }
rectangles = pixman_region32_rectangles(&gs->texture_damage, &n); rectangles = pixman_region32_rectangles(&gb->texture_damage, &n);
wl_shm_buffer_begin_access(buffer->shm_buffer); wl_shm_buffer_begin_access(buffer->shm_buffer);
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
pixman_box32_t r; pixman_box32_t r;
@ -1916,27 +1929,27 @@ gl_renderer_flush_damage(struct weston_surface *surface,
for (j = 0; j < gs->num_textures; j++) { for (j = 0; j < gs->num_textures; j++) {
glBindTexture(GL_TEXTURE_2D, gs->textures[j]); glBindTexture(GL_TEXTURE_2D, gs->textures[j]);
glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT,
gs->pitch / gs->hsub[j]); gb->pitch / gb->hsub[j]);
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT,
r.x1 / gs->hsub[j]); r.x1 / gb->hsub[j]);
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT,
r.y1 / gs->hsub[j]); r.y1 / gb->hsub[j]);
glTexSubImage2D(GL_TEXTURE_2D, 0, glTexSubImage2D(GL_TEXTURE_2D, 0,
r.x1 / gs->hsub[j], r.x1 / gb->hsub[j],
r.y1 / gs->vsub[j], r.y1 / gb->vsub[j],
(r.x2 - r.x1) / gs->hsub[j], (r.x2 - r.x1) / gb->hsub[j],
(r.y2 - r.y1) / gs->vsub[j], (r.y2 - r.y1) / gb->vsub[j],
gl_format_from_internal(gs->gl_format[j]), gl_format_from_internal(gb->gl_format[j]),
gs->gl_pixel_type, gb->gl_pixel_type,
data + gs->offset[j]); data + gb->offset[j]);
} }
} }
wl_shm_buffer_end_access(buffer->shm_buffer); wl_shm_buffer_end_access(buffer->shm_buffer);
done: done:
pixman_region32_fini(&gs->texture_damage); pixman_region32_fini(&gb->texture_damage);
pixman_region32_init(&gs->texture_damage); pixman_region32_init(&gb->texture_damage);
gs->needs_full_upload = false; gb->needs_full_upload = false;
weston_buffer_reference(&gs->buffer_ref, buffer, weston_buffer_reference(&gs->buffer_ref, buffer,
BUFFER_WILL_NOT_BE_ACCESSED); BUFFER_WILL_NOT_BE_ACCESSED);
@ -1949,7 +1962,8 @@ ensure_textures(struct gl_surface_state *gs, GLenum target, int num_textures)
int i; int i;
if (num_textures <= gs->num_textures) { if (num_textures <= gs->num_textures) {
glDeleteTextures(gs->num_textures - num_textures, &gs->textures[num_textures]); glDeleteTextures(gs->num_textures - num_textures,
&gs->textures[num_textures]);
gs->num_textures = num_textures; gs->num_textures = num_textures;
return; return;
} }
@ -1973,6 +1987,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
struct weston_compositor *ec = es->compositor; struct weston_compositor *ec = es->compositor;
struct gl_renderer *gr = get_renderer(ec); struct gl_renderer *gr = get_renderer(ec);
struct gl_surface_state *gs = get_surface_state(es); struct gl_surface_state *gs = get_surface_state(es);
struct gl_buffer_state *gb = &gs->buffer;
GLenum gl_format[3] = {0, 0, 0}; GLenum gl_format[3] = {0, 0, 0};
GLenum gl_pixel_type; GLenum gl_pixel_type;
int pitch; int pitch;
@ -1980,27 +1995,27 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
bool using_glesv2 = gr->gl_version < gr_gl_version(3, 0); bool using_glesv2 = gr->gl_version < gr_gl_version(3, 0);
num_planes = 1; num_planes = 1;
gs->offset[0] = 0; gb->offset[0] = 0;
gs->hsub[0] = 1; gb->hsub[0] = 1;
gs->vsub[0] = 1; gb->vsub[0] = 1;
switch (wl_shm_buffer_get_format(shm_buffer)) { switch (wl_shm_buffer_get_format(shm_buffer)) {
case WL_SHM_FORMAT_XRGB8888: case WL_SHM_FORMAT_XRGB8888:
gs->shader_variant = SHADER_VARIANT_RGBX; gb->shader_variant = SHADER_VARIANT_RGBX;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 4; pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
gl_format[0] = GL_BGRA_EXT; gl_format[0] = GL_BGRA_EXT;
gl_pixel_type = GL_UNSIGNED_BYTE; gl_pixel_type = GL_UNSIGNED_BYTE;
es->is_opaque = true; es->is_opaque = true;
break; break;
case WL_SHM_FORMAT_ARGB8888: case WL_SHM_FORMAT_ARGB8888:
gs->shader_variant = SHADER_VARIANT_RGBA; gb->shader_variant = SHADER_VARIANT_RGBA;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 4; pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
gl_format[0] = GL_BGRA_EXT; gl_format[0] = GL_BGRA_EXT;
gl_pixel_type = GL_UNSIGNED_BYTE; gl_pixel_type = GL_UNSIGNED_BYTE;
es->is_opaque = false; es->is_opaque = false;
break; break;
case WL_SHM_FORMAT_RGB565: case WL_SHM_FORMAT_RGB565:
gs->shader_variant = SHADER_VARIANT_RGBX; gb->shader_variant = SHADER_VARIANT_RGBX;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 2; pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
gl_format[0] = GL_RGB; gl_format[0] = GL_RGB;
gl_pixel_type = GL_UNSIGNED_SHORT_5_6_5; gl_pixel_type = GL_UNSIGNED_SHORT_5_6_5;
@ -2011,7 +2026,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
if (!gr->has_texture_type_2_10_10_10_rev) { if (!gr->has_texture_type_2_10_10_10_rev) {
goto unsupported; goto unsupported;
} }
gs->shader_variant = SHADER_VARIANT_RGBA; gb->shader_variant = SHADER_VARIANT_RGBA;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 4; pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
gl_format[0] = using_glesv2 ? GL_RGBA : GL_RGB10_A2; gl_format[0] = using_glesv2 ? GL_RGBA : GL_RGB10_A2;
gl_pixel_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT; gl_pixel_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT;
@ -2021,7 +2036,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
if (!gr->has_texture_type_2_10_10_10_rev) { if (!gr->has_texture_type_2_10_10_10_rev) {
goto unsupported; goto unsupported;
} }
gs->shader_variant = SHADER_VARIANT_RGBX; gb->shader_variant = SHADER_VARIANT_RGBX;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 4; pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
gl_format[0] = using_glesv2 ? GL_RGBA : GL_RGB10_A2; gl_format[0] = using_glesv2 ? GL_RGBA : GL_RGB10_A2;
gl_pixel_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT; gl_pixel_type = GL_UNSIGNED_INT_2_10_10_10_REV_EXT;
@ -2030,7 +2045,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
case WL_SHM_FORMAT_ABGR16161616F: case WL_SHM_FORMAT_ABGR16161616F:
if (!gr->gl_supports_color_transforms) if (!gr->gl_supports_color_transforms)
goto unsupported; goto unsupported;
gs->shader_variant = SHADER_VARIANT_RGBA; gb->shader_variant = SHADER_VARIANT_RGBA;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 8; pitch = wl_shm_buffer_get_stride(shm_buffer) / 8;
gl_format[0] = GL_RGBA16F; gl_format[0] = GL_RGBA16F;
gl_pixel_type = GL_HALF_FLOAT; gl_pixel_type = GL_HALF_FLOAT;
@ -2039,7 +2054,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
case WL_SHM_FORMAT_XBGR16161616F: case WL_SHM_FORMAT_XBGR16161616F:
if (!gr->gl_supports_color_transforms) if (!gr->gl_supports_color_transforms)
goto unsupported; goto unsupported;
gs->shader_variant = SHADER_VARIANT_RGBX; gb->shader_variant = SHADER_VARIANT_RGBX;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 8; pitch = wl_shm_buffer_get_stride(shm_buffer) / 8;
gl_format[0] = GL_RGBA16F; gl_format[0] = GL_RGBA16F;
gl_pixel_type = GL_HALF_FLOAT; gl_pixel_type = GL_HALF_FLOAT;
@ -2048,7 +2063,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
case WL_SHM_FORMAT_ABGR16161616: case WL_SHM_FORMAT_ABGR16161616:
if (!gr->has_texture_norm16) if (!gr->has_texture_norm16)
goto unsupported; goto unsupported;
gs->shader_variant = SHADER_VARIANT_RGBA; gb->shader_variant = SHADER_VARIANT_RGBA;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 8; pitch = wl_shm_buffer_get_stride(shm_buffer) / 8;
gl_format[0] = GL_RGBA16_EXT; gl_format[0] = GL_RGBA16_EXT;
gl_pixel_type = GL_UNSIGNED_SHORT; gl_pixel_type = GL_UNSIGNED_SHORT;
@ -2057,7 +2072,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
case WL_SHM_FORMAT_XBGR16161616: case WL_SHM_FORMAT_XBGR16161616:
if (!gr->has_texture_norm16) if (!gr->has_texture_norm16)
goto unsupported; goto unsupported;
gs->shader_variant = SHADER_VARIANT_RGBX; gb->shader_variant = SHADER_VARIANT_RGBX;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 8; pitch = wl_shm_buffer_get_stride(shm_buffer) / 8;
gl_format[0] = GL_RGBA16_EXT; gl_format[0] = GL_RGBA16_EXT;
gl_pixel_type = GL_UNSIGNED_SHORT; gl_pixel_type = GL_UNSIGNED_SHORT;
@ -2065,18 +2080,18 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
break; break;
#endif #endif
case WL_SHM_FORMAT_YUV420: case WL_SHM_FORMAT_YUV420:
gs->shader_variant = SHADER_VARIANT_Y_U_V; gb->shader_variant = SHADER_VARIANT_Y_U_V;
pitch = wl_shm_buffer_get_stride(shm_buffer); pitch = wl_shm_buffer_get_stride(shm_buffer);
gl_pixel_type = GL_UNSIGNED_BYTE; gl_pixel_type = GL_UNSIGNED_BYTE;
num_planes = 3; num_planes = 3;
gs->offset[1] = gs->offset[0] + (pitch / gs->hsub[0]) * gb->offset[1] = gb->offset[0] + (pitch / gb->hsub[0]) *
(buffer->height / gs->vsub[0]); (buffer->height / gb->vsub[0]);
gs->hsub[1] = 2; gb->hsub[1] = 2;
gs->vsub[1] = 2; gb->vsub[1] = 2;
gs->offset[2] = gs->offset[1] + (pitch / gs->hsub[1]) * gb->offset[2] = gb->offset[1] + (pitch / gb->hsub[1]) *
(buffer->height / gs->vsub[1]); (buffer->height / gb->vsub[1]);
gs->hsub[2] = 2; gb->hsub[2] = 2;
gs->vsub[2] = 2; gb->vsub[2] = 2;
if (gr->has_gl_texture_rg) { if (gr->has_gl_texture_rg) {
gl_format[0] = GL_R8_EXT; gl_format[0] = GL_R8_EXT;
gl_format[1] = GL_R8_EXT; gl_format[1] = GL_R8_EXT;
@ -2092,29 +2107,29 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
pitch = wl_shm_buffer_get_stride(shm_buffer); pitch = wl_shm_buffer_get_stride(shm_buffer);
gl_pixel_type = GL_UNSIGNED_BYTE; gl_pixel_type = GL_UNSIGNED_BYTE;
num_planes = 2; num_planes = 2;
gs->offset[1] = gs->offset[0] + (pitch / gs->hsub[0]) * gb->offset[1] = gb->offset[0] + (pitch / gb->hsub[0]) *
(buffer->height / gs->vsub[0]); (buffer->height / gb->vsub[0]);
gs->hsub[1] = 2; gb->hsub[1] = 2;
gs->vsub[1] = 2; gb->vsub[1] = 2;
if (gr->has_gl_texture_rg) { if (gr->has_gl_texture_rg) {
gs->shader_variant = SHADER_VARIANT_Y_UV; gb->shader_variant = SHADER_VARIANT_Y_UV;
gl_format[0] = GL_R8_EXT; gl_format[0] = GL_R8_EXT;
gl_format[1] = GL_RG8_EXT; gl_format[1] = GL_RG8_EXT;
} else { } else {
gs->shader_variant = SHADER_VARIANT_Y_XUXV; gb->shader_variant = SHADER_VARIANT_Y_XUXV;
gl_format[0] = GL_LUMINANCE; gl_format[0] = GL_LUMINANCE;
gl_format[1] = GL_LUMINANCE_ALPHA; gl_format[1] = GL_LUMINANCE_ALPHA;
} }
es->is_opaque = true; es->is_opaque = true;
break; break;
case WL_SHM_FORMAT_YUYV: case WL_SHM_FORMAT_YUYV:
gs->shader_variant = SHADER_VARIANT_Y_XUXV; gb->shader_variant = SHADER_VARIANT_Y_XUXV;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 2; pitch = wl_shm_buffer_get_stride(shm_buffer) / 2;
gl_pixel_type = GL_UNSIGNED_BYTE; gl_pixel_type = GL_UNSIGNED_BYTE;
num_planes = 2; num_planes = 2;
gs->offset[1] = 0; gb->offset[1] = 0;
gs->hsub[1] = 2; gb->hsub[1] = 2;
gs->vsub[1] = 1; gb->vsub[1] = 1;
if (gr->has_gl_texture_rg) if (gr->has_gl_texture_rg)
gl_format[0] = GL_RG8_EXT; gl_format[0] = GL_RG8_EXT;
else else
@ -2127,7 +2142,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
* [31:0] X:Y:Cb:Cr 8:8:8:8 little endian * [31:0] X:Y:Cb:Cr 8:8:8:8 little endian
* a:b: g: r in SHADER_VARIANT_XYUV * a:b: g: r in SHADER_VARIANT_XYUV
*/ */
gs->shader_variant = SHADER_VARIANT_XYUV; gb->shader_variant = SHADER_VARIANT_XYUV;
pitch = wl_shm_buffer_get_stride(shm_buffer) / 4; pitch = wl_shm_buffer_get_stride(shm_buffer) / 4;
gl_format[0] = GL_RGBA; gl_format[0] = GL_RGBA;
gl_pixel_type = GL_UNSIGNED_BYTE; gl_pixel_type = GL_UNSIGNED_BYTE;
@ -2143,23 +2158,23 @@ unsupported:
/* Only allocate a texture if it doesn't match existing one. /* Only allocate a texture if it doesn't match existing one.
* If a switch from DRM allocated buffer to a SHM buffer is * If a switch from DRM allocated buffer to a SHM buffer is
* happening, we need to allocate a new texture buffer. */ * happening, we need to allocate a new texture buffer. */
if (pitch != gs->pitch || if (pitch != gb->pitch ||
buffer->height != gs->height || buffer->height != gb->height ||
gl_format[0] != gs->gl_format[0] || gl_format[0] != gb->gl_format[0] ||
gl_format[1] != gs->gl_format[1] || gl_format[1] != gb->gl_format[1] ||
gl_format[2] != gs->gl_format[2] || gl_format[2] != gb->gl_format[2] ||
gl_pixel_type != gs->gl_pixel_type || gl_pixel_type != gb->gl_pixel_type ||
gs->buffer_type != BUFFER_TYPE_SHM) { gb->buffer_type != BUFFER_TYPE_SHM) {
gs->pitch = pitch; gb->pitch = pitch;
gs->height = buffer->height; gb->height = buffer->height;
gs->gl_format[0] = gl_format[0]; gb->gl_format[0] = gl_format[0];
gs->gl_format[1] = gl_format[1]; gb->gl_format[1] = gl_format[1];
gs->gl_format[2] = gl_format[2]; gb->gl_format[2] = gl_format[2];
gs->gl_pixel_type = gl_pixel_type; gb->gl_pixel_type = gl_pixel_type;
gs->buffer_type = BUFFER_TYPE_SHM; gb->buffer_type = BUFFER_TYPE_SHM;
gs->needs_full_upload = true; gb->needs_full_upload = true;
gs->y_inverted = true; gb->y_inverted = true;
gs->direct_display = false; gb->direct_display = false;
gs->surface = es; gs->surface = es;
@ -2235,13 +2250,14 @@ gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
struct weston_compositor *ec = es->compositor; struct weston_compositor *ec = es->compositor;
struct gl_renderer *gr = get_renderer(ec); struct gl_renderer *gr = get_renderer(ec);
struct gl_surface_state *gs = get_surface_state(es); struct gl_surface_state *gs = get_surface_state(es);
struct gl_buffer_state *gb = &gs->buffer;
EGLint attribs[5]; EGLint attribs[5];
GLenum target; GLenum target;
int i, num_planes; int i, num_planes;
for (i = 0; i < gs->num_images; i++) { for (i = 0; i < gb->num_images; i++) {
egl_image_unref(gs->images[i]); egl_image_unref(gb->images[i]);
gs->images[i] = NULL; gb->images[i] = NULL;
} }
es->is_opaque = false; es->is_opaque = false;
switch (format) { switch (format) {
@ -2251,31 +2267,31 @@ gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
case EGL_TEXTURE_RGBA: case EGL_TEXTURE_RGBA:
default: default:
num_planes = 1; num_planes = 1;
gs->shader_variant = SHADER_VARIANT_RGBA; gb->shader_variant = SHADER_VARIANT_RGBA;
break; break;
case EGL_TEXTURE_EXTERNAL_WL: case EGL_TEXTURE_EXTERNAL_WL:
num_planes = 1; num_planes = 1;
gs->shader_variant = SHADER_VARIANT_EXTERNAL; gb->shader_variant = SHADER_VARIANT_EXTERNAL;
break; break;
case EGL_TEXTURE_Y_UV_WL: case EGL_TEXTURE_Y_UV_WL:
num_planes = 2; num_planes = 2;
gs->shader_variant = SHADER_VARIANT_Y_UV; gb->shader_variant = SHADER_VARIANT_Y_UV;
es->is_opaque = true; es->is_opaque = true;
break; break;
case EGL_TEXTURE_Y_U_V_WL: case EGL_TEXTURE_Y_U_V_WL:
num_planes = 3; num_planes = 3;
gs->shader_variant = SHADER_VARIANT_Y_U_V; gb->shader_variant = SHADER_VARIANT_Y_U_V;
es->is_opaque = true; es->is_opaque = true;
break; break;
case EGL_TEXTURE_Y_XUXV_WL: case EGL_TEXTURE_Y_XUXV_WL:
num_planes = 2; num_planes = 2;
gs->shader_variant = SHADER_VARIANT_Y_XUXV; gb->shader_variant = SHADER_VARIANT_Y_XUXV;
es->is_opaque = true; es->is_opaque = true;
break; break;
} }
gs->num_images = num_planes; gb->num_images = num_planes;
target = gl_shader_texture_variant_get_target(gs->shader_variant); target = gl_shader_texture_variant_get_target(gb->shader_variant);
ensure_textures(gs, target, num_planes); ensure_textures(gs, target, num_planes);
for (i = 0; i < num_planes; i++) { for (i = 0; i < num_planes; i++) {
attribs[0] = EGL_WAYLAND_PLANE_WL; attribs[0] = EGL_WAYLAND_PLANE_WL;
@ -2284,24 +2300,24 @@ gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
attribs[3] = EGL_TRUE; attribs[3] = EGL_TRUE;
attribs[4] = EGL_NONE; attribs[4] = EGL_NONE;
gs->images[i] = egl_image_create(gr, gb->images[i] = egl_image_create(gr,
EGL_WAYLAND_BUFFER_WL, EGL_WAYLAND_BUFFER_WL,
buffer->legacy_buffer, buffer->legacy_buffer,
attribs); attribs);
if (!gs->images[i]) { if (!gb->images[i]) {
weston_log("failed to create img for plane %d\n", i); weston_log("failed to create img for plane %d\n", i);
continue; continue;
} }
glActiveTexture(GL_TEXTURE0 + i); glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(target, gs->textures[i]); glBindTexture(target, gs->textures[i]);
gr->image_target_texture_2d(target, gs->images[i]->image); gr->image_target_texture_2d(target, gb->images[i]->image);
} }
gs->pitch = buffer->width; gb->pitch = buffer->width;
gs->height = buffer->height; gb->height = buffer->height;
gs->buffer_type = BUFFER_TYPE_EGL; gb->buffer_type = BUFFER_TYPE_EGL;
gs->y_inverted = (buffer->buffer_origin == ORIGIN_TOP_LEFT); gb->y_inverted = (buffer->buffer_origin == ORIGIN_TOP_LEFT);
} }
static void static void
@ -2869,19 +2885,20 @@ gl_renderer_attach_dmabuf(struct weston_surface *surface,
{ {
struct gl_renderer *gr = get_renderer(surface->compositor); struct gl_renderer *gr = get_renderer(surface->compositor);
struct gl_surface_state *gs = get_surface_state(surface); struct gl_surface_state *gs = get_surface_state(surface);
struct gl_buffer_state *gb = &gs->buffer;
struct dmabuf_image *image; struct dmabuf_image *image;
GLenum target; GLenum target;
int i; int i;
for (i = 0; i < gs->num_images; i++) for (i = 0; i < gb->num_images; i++)
egl_image_unref(gs->images[i]); egl_image_unref(gb->images[i]);
gs->num_images = 0; gb->num_images = 0;
gs->pitch = buffer->width; gb->pitch = buffer->width;
gs->height = buffer->height; gb->height = buffer->height;
gs->buffer_type = BUFFER_TYPE_EGL; gb->buffer_type = BUFFER_TYPE_EGL;
gs->y_inverted = (buffer->buffer_origin == ORIGIN_TOP_LEFT); gb->y_inverted = (buffer->buffer_origin == ORIGIN_TOP_LEFT);
gs->direct_display = dmabuf->direct_display; gb->direct_display = dmabuf->direct_display;
surface->is_opaque = pixel_format_is_opaque(buffer->pixel_format); surface->is_opaque = pixel_format_is_opaque(buffer->pixel_format);
if (dmabuf->direct_display) if (dmabuf->direct_display)
@ -2892,19 +2909,19 @@ gl_renderer_attach_dmabuf(struct weston_surface *surface,
/* The dmabuf_image should have been created during the import */ /* The dmabuf_image should have been created during the import */
assert(image != NULL); assert(image != NULL);
gs->num_images = image->num_images; gb->num_images = image->num_images;
for (i = 0; i < gs->num_images; ++i) for (i = 0; i < gb->num_images; ++i)
gs->images[i] = egl_image_ref(image->images[i]); gb->images[i] = egl_image_ref(image->images[i]);
target = gl_shader_texture_variant_get_target(image->shader_variant); target = gl_shader_texture_variant_get_target(image->shader_variant);
ensure_textures(gs, target, gs->num_images); ensure_textures(gs, target, gb->num_images);
for (i = 0; i < gs->num_images; ++i) { for (i = 0; i < gb->num_images; ++i) {
glActiveTexture(GL_TEXTURE0 + i); glActiveTexture(GL_TEXTURE0 + i);
glBindTexture(target, gs->textures[i]); glBindTexture(target, gs->textures[i]);
gr->image_target_texture_2d(target, gs->images[i]->image); gr->image_target_texture_2d(target, gb->images[i]->image);
} }
gs->shader_variant = image->shader_variant; gb->shader_variant = image->shader_variant;
} }
static const struct weston_drm_format_array * static const struct weston_drm_format_array *
@ -2977,16 +2994,17 @@ gl_renderer_surface_set_color(struct weston_surface *surface,
float red, float green, float blue, float alpha) float red, float green, float blue, float alpha)
{ {
struct gl_surface_state *gs = get_surface_state(surface); struct gl_surface_state *gs = get_surface_state(surface);
struct gl_buffer_state *gb = &gs->buffer;
gs->color[0] = red; gb->color[0] = red;
gs->color[1] = green; gb->color[1] = green;
gs->color[2] = blue; gb->color[2] = blue;
gs->color[3] = alpha; gb->color[3] = alpha;
gs->buffer_type = BUFFER_TYPE_SOLID; gb->buffer_type = BUFFER_TYPE_SOLID;
gs->pitch = 1; gb->pitch = 1;
gs->height = 1; gb->height = 1;
gs->shader_variant = SHADER_VARIANT_SOLID; gb->shader_variant = SHADER_VARIANT_SOLID;
} }
static void static void
@ -2995,6 +3013,7 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
struct weston_compositor *ec = es->compositor; struct weston_compositor *ec = es->compositor;
struct gl_renderer *gr = get_renderer(ec); struct gl_renderer *gr = get_renderer(ec);
struct gl_surface_state *gs = get_surface_state(es); struct gl_surface_state *gs = get_surface_state(es);
struct gl_buffer_state *gb = &gs->buffer;
EGLint format; EGLint format;
int i; int i;
@ -3005,16 +3024,16 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
es->buffer_release_ref.buffer_release); es->buffer_release_ref.buffer_release);
if (!buffer) { if (!buffer) {
for (i = 0; i < gs->num_images; i++) { for (i = 0; i < gb->num_images; i++) {
egl_image_unref(gs->images[i]); egl_image_unref(gb->images[i]);
gs->images[i] = NULL; gb->images[i] = NULL;
} }
gs->num_images = 0; gb->num_images = 0;
glDeleteTextures(gs->num_textures, gs->textures); glDeleteTextures(gs->num_textures, gs->textures);
gs->num_textures = 0; gs->num_textures = 0;
gs->buffer_type = BUFFER_TYPE_NULL; gb->buffer_type = BUFFER_TYPE_NULL;
gs->y_inverted = true; gb->y_inverted = true;
gs->direct_display = false; gb->direct_display = false;
es->is_opaque = false; es->is_opaque = false;
return; return;
} }
@ -3057,8 +3076,8 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
weston_buffer_reference(&gs->buffer_ref, NULL, weston_buffer_reference(&gs->buffer_ref, NULL,
BUFFER_WILL_NOT_BE_ACCESSED); BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&gs->buffer_release_ref, NULL); weston_buffer_release_reference(&gs->buffer_release_ref, NULL);
gs->buffer_type = BUFFER_TYPE_NULL; gb->buffer_type = BUFFER_TYPE_NULL;
gs->y_inverted = true; gb->y_inverted = true;
es->is_opaque = false; es->is_opaque = false;
weston_buffer_send_server_error(buffer, weston_buffer_send_server_error(buffer,
"disconnecting due to unhandled buffer type"); "disconnecting due to unhandled buffer type");
@ -3069,13 +3088,14 @@ gl_renderer_surface_get_content_size(struct weston_surface *surface,
int *width, int *height) int *width, int *height)
{ {
struct gl_surface_state *gs = get_surface_state(surface); struct gl_surface_state *gs = get_surface_state(surface);
struct gl_buffer_state *gb = &gs->buffer;
if (gs->buffer_type == BUFFER_TYPE_NULL) { if (gb->buffer_type == BUFFER_TYPE_NULL) {
*width = 0; *width = 0;
*height = 0; *height = 0;
} else { } else {
*width = gs->pitch; *width = gb->pitch;
*height = gs->height; *height = gb->height;
} }
} }
@ -3129,6 +3149,7 @@ gl_renderer_surface_copy_content(struct weston_surface *surface,
const GLenum gl_format = GL_RGBA; /* PIXMAN_a8b8g8r8 little-endian */ const GLenum gl_format = GL_RGBA; /* PIXMAN_a8b8g8r8 little-endian */
struct gl_renderer *gr = get_renderer(surface->compositor); struct gl_renderer *gr = get_renderer(surface->compositor);
struct gl_surface_state *gs = get_surface_state(surface); struct gl_surface_state *gs = get_surface_state(surface);
struct gl_buffer_state *gb = &gs->buffer;
int cw, ch; int cw, ch;
GLuint fbo; GLuint fbo;
GLuint tex; GLuint tex;
@ -3137,11 +3158,11 @@ gl_renderer_surface_copy_content(struct weston_surface *surface,
gl_renderer_surface_get_content_size(surface, &cw, &ch); gl_renderer_surface_get_content_size(surface, &cw, &ch);
switch (gs->buffer_type) { switch (gb->buffer_type) {
case BUFFER_TYPE_NULL: case BUFFER_TYPE_NULL:
return -1; return -1;
case BUFFER_TYPE_SOLID: case BUFFER_TYPE_SOLID:
*(uint32_t *)target = pack_color(format, gs->color); *(uint32_t *)target = pack_color(format, gb->color);
return 0; return 0;
case BUFFER_TYPE_SHM: case BUFFER_TYPE_SHM:
gl_renderer_flush_damage(surface, gs->buffer_ref.buffer); gl_renderer_flush_damage(surface, gs->buffer_ref.buffer);
@ -3172,7 +3193,7 @@ gl_renderer_surface_copy_content(struct weston_surface *surface,
glViewport(0, 0, cw, ch); glViewport(0, 0, cw, ch);
glDisable(GL_BLEND); glDisable(GL_BLEND);
if (gs->y_inverted) if (gb->y_inverted)
ARRAY_COPY(sconf.projection.d, projmat_normal); ARRAY_COPY(sconf.projection.d, projmat_normal);
else else
ARRAY_COPY(sconf.projection.d, projmat_yinvert); ARRAY_COPY(sconf.projection.d, projmat_yinvert);
@ -3210,6 +3231,7 @@ out:
static void static void
surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr) surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
{ {
struct gl_buffer_state *gb = &gs->buffer;
int i; int i;
wl_list_remove(&gs->surface_destroy_listener.link); wl_list_remove(&gs->surface_destroy_listener.link);
@ -3219,13 +3241,13 @@ surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
glDeleteTextures(gs->num_textures, gs->textures); glDeleteTextures(gs->num_textures, gs->textures);
for (i = 0; i < gs->num_images; i++) for (i = 0; i < gb->num_images; i++)
egl_image_unref(gs->images[i]); egl_image_unref(gb->images[i]);
weston_buffer_reference(&gs->buffer_ref, NULL, weston_buffer_reference(&gs->buffer_ref, NULL,
BUFFER_WILL_NOT_BE_ACCESSED); BUFFER_WILL_NOT_BE_ACCESSED);
weston_buffer_release_reference(&gs->buffer_release_ref, NULL); weston_buffer_release_reference(&gs->buffer_release_ref, NULL);
pixman_region32_fini(&gs->texture_damage); pixman_region32_fini(&gb->texture_damage);
free(gs); free(gs);
} }
@ -3261,23 +3283,25 @@ static int
gl_renderer_create_surface(struct weston_surface *surface) gl_renderer_create_surface(struct weston_surface *surface)
{ {
struct gl_surface_state *gs; struct gl_surface_state *gs;
struct gl_buffer_state *gb;
struct gl_renderer *gr = get_renderer(surface->compositor); struct gl_renderer *gr = get_renderer(surface->compositor);
gs = zalloc(sizeof *gs); gs = zalloc(sizeof *gs);
if (gs == NULL) if (gs == NULL)
return -1; return -1;
gb = &gs->buffer;
/* A buffer is never attached to solid color surfaces, yet /* A buffer is never attached to solid color surfaces, yet
* they still go through texcoord computations. Do not divide * they still go through texcoord computations. Do not divide
* by zero there. * by zero there.
*/ */
gs->pitch = 1; gb->pitch = 1;
gs->y_inverted = true; gb->y_inverted = true;
gs->direct_display = false; gb->direct_display = false;
gs->surface = surface; gs->surface = surface;
pixman_region32_init(&gs->texture_damage); pixman_region32_init(&gb->texture_damage);
surface->renderer_state = gs; surface->renderer_state = gs;
gs->surface_destroy_listener.notify = gs->surface_destroy_listener.notify =

Loading…
Cancel
Save