[weston 1/2] gl-renderer: add support of WL_SHM_FORMAT_YUV420
Vincent Abriou
vincent.abriou at st.com
Fri Aug 5 09:21:44 UTC 2016
This patch allow weston to accept WL_SHM_FORMAT_YUV420 buffers.
In a gstreamer pipeline, the support of the WL_SHM_FORMAT_YUV420 by
weston avoid pixel conversion between software decoders and waylandsink.
Indeed, software decoders output I420 (YUV420 planar) that will
match with WL_SHM_FORMAT_YUV420.
It has been tested on top of weston-1.11
Signed-off-by: Vincent Abriou <vincent.abriou at st.com>
---
libweston/gl-renderer.c | 56 ++++++++++++++++++++++++++++++++++++-------------
1 file changed, 42 insertions(+), 14 deletions(-)
diff --git a/libweston/gl-renderer.c b/libweston/gl-renderer.c
index ed44c6d..12b763e 100644
--- a/libweston/gl-renderer.c
+++ b/libweston/gl-renderer.c
@@ -160,6 +160,10 @@ struct gl_surface_state {
int height; /* in pixels */
int y_inverted;
+ /* Extension needed for SHM YUV texture */
+ int offset[3]; /* offet per plane */
+ int hvsub[3]; /* horizontal vertical subsampling per plane */
+
struct weston_surface *surface;
struct wl_listener surface_destroy_listener;
@@ -1228,7 +1232,7 @@ gl_renderer_flush_damage(struct weston_surface *surface)
bool texture_used;
pixman_box32_t *rectangles;
void *data;
- int i, n;
+ int i, j, n;
pixman_region32_union(&gs->texture_damage,
&gs->texture_damage, &surface->damage);
@@ -1255,14 +1259,15 @@ gl_renderer_flush_damage(struct weston_surface *surface)
!gs->needs_full_upload)
goto done;
- glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
-
if (!gr->has_unpack_subimage) {
wl_shm_buffer_begin_access(buffer->shm_buffer);
- glTexImage2D(GL_TEXTURE_2D, 0, gs->gl_format,
- gs->pitch, buffer->height, 0,
- gs->gl_format, gs->gl_pixel_type,
- wl_shm_buffer_get_data(buffer->shm_buffer));
+ for (j = 0; j < gs->num_textures; j++) {
+ glBindTexture(GL_TEXTURE_2D, gs->textures[j]);
+ glTexImage2D(GL_TEXTURE_2D, 0, gs->gl_format,
+ gs->pitch / gs->hvsub[j], buffer->height / gs->hvsub[j], 0,
+ gs->gl_format, gs->gl_pixel_type,
+ wl_shm_buffer_get_data(buffer->shm_buffer) + gs->offset[j]);
+ }
wl_shm_buffer_end_access(buffer->shm_buffer);
goto done;
@@ -1275,9 +1280,12 @@ gl_renderer_flush_damage(struct weston_surface *surface)
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
wl_shm_buffer_begin_access(buffer->shm_buffer);
- glTexImage2D(GL_TEXTURE_2D, 0, gs->gl_format,
- gs->pitch, buffer->height, 0,
- gs->gl_format, gs->gl_pixel_type, data);
+ for (j = 0; j < gs->num_textures; j++) {
+ glBindTexture(GL_TEXTURE_2D, gs->textures[j]);
+ glTexImage2D(GL_TEXTURE_2D, 0, gs->gl_format,
+ gs->pitch / gs->hvsub[j], buffer->height / gs->hvsub[j], 0,
+ gs->gl_format, gs->gl_pixel_type, data + gs->offset[j]);
+ }
wl_shm_buffer_end_access(buffer->shm_buffer);
goto done;
}
@@ -1291,9 +1299,12 @@ gl_renderer_flush_damage(struct weston_surface *surface)
glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, r.x1);
glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, r.y1);
- glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1, r.y1,
- r.x2 - r.x1, r.y2 - r.y1,
- gs->gl_format, gs->gl_pixel_type, data);
+ for (j = 0; j < gs->num_textures; j++) {
+ glBindTexture(GL_TEXTURE_2D, gs->textures[j]);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, r.x1 / gs->hvsub[j], r.y1 / gs->hvsub[j],
+ (r.x2 - r.x1) / gs->hvsub[j], (r.y2 - r.y1) / gs->hvsub[j],
+ gs->gl_format, gs->gl_pixel_type, data + gs->offset[j]);
+ }
}
wl_shm_buffer_end_access(buffer->shm_buffer);
@@ -1334,11 +1345,16 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
struct gl_surface_state *gs = get_surface_state(es);
GLenum gl_format, gl_pixel_type;
int pitch;
+ int num_planes;
buffer->shm_buffer = shm_buffer;
buffer->width = wl_shm_buffer_get_width(shm_buffer);
buffer->height = wl_shm_buffer_get_height(shm_buffer);
+ num_planes = 1;
+ gs->offset[0] = 0;
+ gs->hvsub[0] = 1;
+
switch (wl_shm_buffer_get_format(shm_buffer)) {
case WL_SHM_FORMAT_XRGB8888:
gs->shader = &gr->texture_shader_rgbx;
@@ -1358,6 +1374,17 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
gl_format = GL_RGB;
gl_pixel_type = GL_UNSIGNED_SHORT_5_6_5;
break;
+ case WL_SHM_FORMAT_YUV420:
+ gs->shader = &gr->texture_shader_y_u_v;
+ pitch = wl_shm_buffer_get_stride(shm_buffer);
+ gl_format = GL_LUMINANCE;
+ gl_pixel_type = GL_UNSIGNED_BYTE;
+ num_planes = 3;
+ gs->offset[1] = gs->offset[0] + (pitch / gs->hvsub[0]) * (buffer->height / gs->hvsub[0]);
+ gs->hvsub[1] = 2;
+ gs->offset[2] = gs->offset[1] + (pitch / gs->hvsub[1]) * (buffer->height / gs->hvsub[1]);
+ gs->hvsub[2] = 2;
+ break;
default:
weston_log("warning: unknown shm buffer format: %08x\n",
wl_shm_buffer_get_format(shm_buffer));
@@ -1383,7 +1410,7 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer,
gs->surface = es;
- ensure_textures(gs, 1);
+ ensure_textures(gs, num_planes);
}
}
@@ -2961,6 +2988,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLenum platform,
}
wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_RGB565);
+ wl_display_add_shm_format(ec->wl_display, WL_SHM_FORMAT_YUV420);
wl_signal_init(&gr->destroy_signal);
--
1.9.1
More information about the wayland-devel
mailing list