|
|
|
@ -1200,6 +1200,116 @@ ensure_textures(struct gl_surface_state *gs, int num_textures) |
|
|
|
|
glBindTexture(gs->target, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer, |
|
|
|
|
struct wl_shm_buffer *shm_buffer) |
|
|
|
|
{ |
|
|
|
|
struct weston_compositor *ec = es->compositor; |
|
|
|
|
struct gl_renderer *gr = get_renderer(ec); |
|
|
|
|
struct gl_surface_state *gs = get_surface_state(es); |
|
|
|
|
|
|
|
|
|
buffer->shm_buffer = shm_buffer; |
|
|
|
|
buffer->width = wl_shm_buffer_get_width(shm_buffer); |
|
|
|
|
buffer->height = wl_shm_buffer_get_height(shm_buffer); |
|
|
|
|
|
|
|
|
|
/* Only allocate a texture if it doesn't match existing one.
|
|
|
|
|
* If a switch from DRM allocated buffer to a SHM buffer is |
|
|
|
|
* happening, we need to allocate a new texture buffer. */ |
|
|
|
|
if (wl_shm_buffer_get_stride(shm_buffer) / 4 != gs->pitch || |
|
|
|
|
buffer->height != gs->height || |
|
|
|
|
gs->buffer_type != BUFFER_TYPE_SHM) { |
|
|
|
|
gs->pitch = wl_shm_buffer_get_stride(shm_buffer) / 4; |
|
|
|
|
gs->height = buffer->height; |
|
|
|
|
gs->target = GL_TEXTURE_2D; |
|
|
|
|
gs->buffer_type = BUFFER_TYPE_SHM; |
|
|
|
|
gs->needs_full_upload = 1; |
|
|
|
|
|
|
|
|
|
ensure_textures(gs, 1); |
|
|
|
|
glBindTexture(GL_TEXTURE_2D, gs->textures[0]); |
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, |
|
|
|
|
gs->pitch, buffer->height, 0, |
|
|
|
|
GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (wl_shm_buffer_get_format(shm_buffer) == WL_SHM_FORMAT_XRGB8888) |
|
|
|
|
gs->shader = &gr->texture_shader_rgbx; |
|
|
|
|
else |
|
|
|
|
gs->shader = &gr->texture_shader_rgba; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer, |
|
|
|
|
uint32_t format) |
|
|
|
|
{ |
|
|
|
|
struct weston_compositor *ec = es->compositor; |
|
|
|
|
struct gl_renderer *gr = get_renderer(ec); |
|
|
|
|
struct gl_surface_state *gs = get_surface_state(es); |
|
|
|
|
EGLint attribs[3]; |
|
|
|
|
int i, num_planes; |
|
|
|
|
|
|
|
|
|
buffer->legacy_buffer = (struct wl_buffer *)buffer->resource; |
|
|
|
|
gr->query_buffer(gr->egl_display, buffer->legacy_buffer, |
|
|
|
|
EGL_WIDTH, &buffer->width); |
|
|
|
|
gr->query_buffer(gr->egl_display, buffer->legacy_buffer, |
|
|
|
|
EGL_HEIGHT, &buffer->height); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < gs->num_images; i++) |
|
|
|
|
gr->destroy_image(gr->egl_display, gs->images[i]); |
|
|
|
|
gs->num_images = 0; |
|
|
|
|
gs->target = GL_TEXTURE_2D; |
|
|
|
|
switch (format) { |
|
|
|
|
case EGL_TEXTURE_RGB: |
|
|
|
|
case EGL_TEXTURE_RGBA: |
|
|
|
|
default: |
|
|
|
|
num_planes = 1; |
|
|
|
|
gs->shader = &gr->texture_shader_rgba; |
|
|
|
|
break; |
|
|
|
|
case EGL_TEXTURE_EXTERNAL_WL: |
|
|
|
|
num_planes = 1; |
|
|
|
|
gs->target = GL_TEXTURE_EXTERNAL_OES; |
|
|
|
|
gs->shader = &gr->texture_shader_egl_external; |
|
|
|
|
break; |
|
|
|
|
case EGL_TEXTURE_Y_UV_WL: |
|
|
|
|
num_planes = 2; |
|
|
|
|
gs->shader = &gr->texture_shader_y_uv; |
|
|
|
|
break; |
|
|
|
|
case EGL_TEXTURE_Y_U_V_WL: |
|
|
|
|
num_planes = 3; |
|
|
|
|
gs->shader = &gr->texture_shader_y_u_v; |
|
|
|
|
break; |
|
|
|
|
case EGL_TEXTURE_Y_XUXV_WL: |
|
|
|
|
num_planes = 2; |
|
|
|
|
gs->shader = &gr->texture_shader_y_xuxv; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ensure_textures(gs, num_planes); |
|
|
|
|
for (i = 0; i < num_planes; i++) { |
|
|
|
|
attribs[0] = EGL_WAYLAND_PLANE_WL; |
|
|
|
|
attribs[1] = i; |
|
|
|
|
attribs[2] = EGL_NONE; |
|
|
|
|
gs->images[i] = gr->create_image(gr->egl_display, |
|
|
|
|
NULL, |
|
|
|
|
EGL_WAYLAND_BUFFER_WL, |
|
|
|
|
buffer->legacy_buffer, |
|
|
|
|
attribs); |
|
|
|
|
if (!gs->images[i]) { |
|
|
|
|
weston_log("failed to create img for plane %d\n", i); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
gs->num_images++; |
|
|
|
|
|
|
|
|
|
glActiveTexture(GL_TEXTURE0 + i); |
|
|
|
|
glBindTexture(gs->target, gs->textures[i]); |
|
|
|
|
gr->image_target_texture_2d(gs->target, |
|
|
|
|
gs->images[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gs->pitch = buffer->width; |
|
|
|
|
gs->height = buffer->height; |
|
|
|
|
gs->buffer_type = BUFFER_TYPE_EGL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) |
|
|
|
|
{ |
|
|
|
@ -1207,8 +1317,8 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) |
|
|
|
|
struct gl_renderer *gr = get_renderer(ec); |
|
|
|
|
struct gl_surface_state *gs = get_surface_state(es); |
|
|
|
|
struct wl_shm_buffer *shm_buffer; |
|
|
|
|
EGLint attribs[3], format; |
|
|
|
|
int i, num_planes; |
|
|
|
|
EGLint format; |
|
|
|
|
int i; |
|
|
|
|
|
|
|
|
|
weston_buffer_reference(&gs->buffer_ref, buffer); |
|
|
|
|
|
|
|
|
@ -1225,99 +1335,14 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
shm_buffer = wl_shm_buffer_get(buffer->resource); |
|
|
|
|
if (shm_buffer) { |
|
|
|
|
buffer->shm_buffer = shm_buffer; |
|
|
|
|
buffer->width = wl_shm_buffer_get_width(shm_buffer); |
|
|
|
|
buffer->height = wl_shm_buffer_get_height(shm_buffer); |
|
|
|
|
|
|
|
|
|
/* Only allocate a texture if it doesn't match existing one.
|
|
|
|
|
* If a switch from DRM allocated buffer to a SHM buffer is |
|
|
|
|
* happening, we need to allocate a new texture buffer. */ |
|
|
|
|
if (wl_shm_buffer_get_stride(shm_buffer) / 4 != gs->pitch || |
|
|
|
|
buffer->height != gs->height || |
|
|
|
|
gs->buffer_type != BUFFER_TYPE_SHM) { |
|
|
|
|
gs->pitch = wl_shm_buffer_get_stride(shm_buffer) / 4; |
|
|
|
|
gs->height = buffer->height; |
|
|
|
|
gs->target = GL_TEXTURE_2D; |
|
|
|
|
gs->buffer_type = BUFFER_TYPE_SHM; |
|
|
|
|
gs->needs_full_upload = 1; |
|
|
|
|
|
|
|
|
|
ensure_textures(gs, 1); |
|
|
|
|
glBindTexture(GL_TEXTURE_2D, gs->textures[0]); |
|
|
|
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, |
|
|
|
|
gs->pitch, buffer->height, 0, |
|
|
|
|
GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (wl_shm_buffer_get_format(shm_buffer) == WL_SHM_FORMAT_XRGB8888) |
|
|
|
|
gs->shader = &gr->texture_shader_rgbx; |
|
|
|
|
else |
|
|
|
|
gs->shader = &gr->texture_shader_rgba; |
|
|
|
|
} else if (gr->query_buffer(gr->egl_display, |
|
|
|
|
(struct wl_buffer *)buffer->resource, |
|
|
|
|
EGL_TEXTURE_FORMAT, &format)) { |
|
|
|
|
buffer->legacy_buffer = (struct wl_buffer *)buffer->resource; |
|
|
|
|
gr->query_buffer(gr->egl_display, buffer->legacy_buffer, |
|
|
|
|
EGL_WIDTH, &buffer->width); |
|
|
|
|
gr->query_buffer(gr->egl_display, buffer->legacy_buffer, |
|
|
|
|
EGL_HEIGHT, &buffer->height); |
|
|
|
|
|
|
|
|
|
for (i = 0; i < gs->num_images; i++) |
|
|
|
|
gr->destroy_image(gr->egl_display, gs->images[i]); |
|
|
|
|
gs->num_images = 0; |
|
|
|
|
gs->target = GL_TEXTURE_2D; |
|
|
|
|
switch (format) { |
|
|
|
|
case EGL_TEXTURE_RGB: |
|
|
|
|
case EGL_TEXTURE_RGBA: |
|
|
|
|
default: |
|
|
|
|
num_planes = 1; |
|
|
|
|
gs->shader = &gr->texture_shader_rgba; |
|
|
|
|
break; |
|
|
|
|
case EGL_TEXTURE_EXTERNAL_WL: |
|
|
|
|
num_planes = 1; |
|
|
|
|
gs->target = GL_TEXTURE_EXTERNAL_OES; |
|
|
|
|
gs->shader = &gr->texture_shader_egl_external; |
|
|
|
|
break; |
|
|
|
|
case EGL_TEXTURE_Y_UV_WL: |
|
|
|
|
num_planes = 2; |
|
|
|
|
gs->shader = &gr->texture_shader_y_uv; |
|
|
|
|
break; |
|
|
|
|
case EGL_TEXTURE_Y_U_V_WL: |
|
|
|
|
num_planes = 3; |
|
|
|
|
gs->shader = &gr->texture_shader_y_u_v; |
|
|
|
|
break; |
|
|
|
|
case EGL_TEXTURE_Y_XUXV_WL: |
|
|
|
|
num_planes = 2; |
|
|
|
|
gs->shader = &gr->texture_shader_y_xuxv; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ensure_textures(gs, num_planes); |
|
|
|
|
for (i = 0; i < num_planes; i++) { |
|
|
|
|
attribs[0] = EGL_WAYLAND_PLANE_WL; |
|
|
|
|
attribs[1] = i; |
|
|
|
|
attribs[2] = EGL_NONE; |
|
|
|
|
gs->images[i] = gr->create_image(gr->egl_display, |
|
|
|
|
NULL, |
|
|
|
|
EGL_WAYLAND_BUFFER_WL, |
|
|
|
|
buffer->legacy_buffer, |
|
|
|
|
attribs); |
|
|
|
|
if (!gs->images[i]) { |
|
|
|
|
weston_log("failed to create img for plane %d\n", i); |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
gs->num_images++; |
|
|
|
|
|
|
|
|
|
glActiveTexture(GL_TEXTURE0 + i); |
|
|
|
|
glBindTexture(gs->target, gs->textures[i]); |
|
|
|
|
gr->image_target_texture_2d(gs->target, |
|
|
|
|
gs->images[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
gs->pitch = buffer->width; |
|
|
|
|
gs->height = buffer->height; |
|
|
|
|
gs->buffer_type = BUFFER_TYPE_EGL; |
|
|
|
|
} else { |
|
|
|
|
if (shm_buffer) |
|
|
|
|
gl_renderer_attach_shm(es, buffer, shm_buffer); |
|
|
|
|
else if (gr->query_buffer(gr->egl_display, |
|
|
|
|
(struct wl_buffer *)buffer->resource, |
|
|
|
|
EGL_TEXTURE_FORMAT, &format)) |
|
|
|
|
gl_renderer_attach_egl(es, buffer, format); |
|
|
|
|
else { |
|
|
|
|
weston_log("unhandled buffer type!\n"); |
|
|
|
|
weston_buffer_reference(&gs->buffer_ref, NULL); |
|
|
|
|
gs->buffer_type = BUFFER_TYPE_NULL; |
|
|
|
|