CoglBool cogl_wayland_texture_set_region_from_shm_buffer (CoglTexture *texture, int src_x, int src_y, int width, int height, struct wl_shm_buffer * shm_buffer, int dst_x, int dst_y, int level, CoglError **error) { const uint8_t *data = wl_shm_buffer_get_data (shm_buffer); int32_t stride = wl_shm_buffer_get_stride (shm_buffer); CoglPixelFormat format; int bpp; shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL); bpp = _cogl_pixel_format_get_bytes_per_pixel (format); return cogl_texture_set_region (COGL_TEXTURE (texture), width, height, format, stride, data + src_x * bpp + src_y * stride, dst_x, dst_y, level, error); }
static gboolean process_shm_buffer_damage (MetaWaylandBuffer *buffer, CoglTexture *texture, cairo_region_t *region, GError **error) { struct wl_shm_buffer *shm_buffer; int i, n_rectangles; gboolean set_texture_failed = FALSE; n_rectangles = cairo_region_num_rectangles (region); shm_buffer = wl_shm_buffer_get (buffer->resource); wl_shm_buffer_begin_access (shm_buffer); for (i = 0; i < n_rectangles; i++) { const uint8_t *data = wl_shm_buffer_get_data (shm_buffer); int32_t stride = wl_shm_buffer_get_stride (shm_buffer); CoglPixelFormat format; int bpp; cairo_rectangle_int_t rect; shm_buffer_get_cogl_pixel_format (shm_buffer, &format, NULL); bpp = _cogl_pixel_format_get_bytes_per_pixel (format); cairo_region_get_rectangle (region, i, &rect); if (!_cogl_texture_set_region (texture, rect.width, rect.height, format, stride, data + rect.x * bpp + rect.y * stride, rect.x, rect.y, 0, error)) { set_texture_failed = TRUE; break; } } wl_shm_buffer_end_access (shm_buffer); return !set_texture_failed; }
CoglTexture2D * cogl_wayland_texture_2d_new_from_buffer (CoglContext *ctx, struct wl_resource *buffer, CoglError **error) { struct wl_shm_buffer *shm_buffer; CoglTexture2D *tex = NULL; shm_buffer = wl_shm_buffer_get (buffer); if (shm_buffer) { int stride = wl_shm_buffer_get_stride (shm_buffer); int width = wl_shm_buffer_get_width (shm_buffer); int height = wl_shm_buffer_get_height (shm_buffer); CoglPixelFormat format; CoglTextureComponents components; CoglBitmap *bmp; shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &components); bmp = cogl_bitmap_new_for_data (ctx, width, height, format, stride, wl_shm_buffer_get_data (shm_buffer)); tex = cogl_texture_2d_new_from_bitmap (bmp); cogl_texture_set_components (COGL_TEXTURE (tex), components); cogl_object_unref (bmp); if (!cogl_texture_allocate (COGL_TEXTURE (tex), error)) { cogl_object_unref (tex); return NULL; } else return tex; } else { int format, width, height; if (_cogl_egl_query_wayland_buffer (ctx, buffer, EGL_TEXTURE_FORMAT, &format) && _cogl_egl_query_wayland_buffer (ctx, buffer, EGL_WIDTH, &width) && _cogl_egl_query_wayland_buffer (ctx, buffer, EGL_HEIGHT, &height)) { EGLImageKHR image; CoglPixelFormat internal_format; _COGL_RETURN_VAL_IF_FAIL (_cogl_context_get_winsys (ctx)->constraints & COGL_RENDERER_CONSTRAINT_USES_EGL, NULL); switch (format) { case EGL_TEXTURE_RGB: internal_format = COGL_PIXEL_FORMAT_RGB_888; break; case EGL_TEXTURE_RGBA: internal_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE; break; default: _cogl_set_error (error, COGL_SYSTEM_ERROR, COGL_SYSTEM_ERROR_UNSUPPORTED, "Can't create texture from unknown " "wayland buffer format %d\n", format); return NULL; } image = _cogl_egl_create_image (ctx, EGL_WAYLAND_BUFFER_WL, buffer, NULL); tex = _cogl_egl_texture_2d_new_from_image (ctx, width, height, internal_format, image, error); _cogl_egl_destroy_image (ctx, image); return tex; } } _cogl_set_error (error, COGL_SYSTEM_ERROR, COGL_SYSTEM_ERROR_UNSUPPORTED, "Can't create texture from unknown " "wayland buffer type\n"); return NULL; }
static gboolean shm_buffer_attach (MetaWaylandBuffer *buffer, CoglTexture **texture, gboolean *changed_texture, GError **error) { MetaBackend *backend = meta_get_backend (); ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend); struct wl_shm_buffer *shm_buffer; int stride, width, height; CoglPixelFormat format; CoglTextureComponents components; CoglBitmap *bitmap; CoglTexture *new_texture; shm_buffer = wl_shm_buffer_get (buffer->resource); stride = wl_shm_buffer_get_stride (shm_buffer); width = wl_shm_buffer_get_width (shm_buffer); height = wl_shm_buffer_get_height (shm_buffer); shm_buffer_get_cogl_pixel_format (shm_buffer, &format, &components); if (*texture && cogl_texture_get_width (*texture) == width && cogl_texture_get_height (*texture) == height && cogl_texture_get_components (*texture) == components && _cogl_texture_get_format (*texture) == format) { buffer->is_y_inverted = TRUE; *changed_texture = FALSE; return TRUE; } cogl_clear_object (texture); wl_shm_buffer_begin_access (shm_buffer); bitmap = cogl_bitmap_new_for_data (cogl_context, width, height, format, stride, wl_shm_buffer_get_data (shm_buffer)); new_texture = COGL_TEXTURE (cogl_texture_2d_new_from_bitmap (bitmap)); cogl_texture_set_components (new_texture, components); if (!cogl_texture_allocate (new_texture, error)) { g_clear_pointer (&new_texture, cogl_object_unref); if (g_error_matches (*error, COGL_TEXTURE_ERROR, COGL_TEXTURE_ERROR_SIZE)) { CoglTexture2DSliced *texture_sliced; g_clear_error (error); texture_sliced = cogl_texture_2d_sliced_new_from_bitmap (bitmap, COGL_TEXTURE_MAX_WASTE); new_texture = COGL_TEXTURE (texture_sliced); cogl_texture_set_components (new_texture, components); if (!cogl_texture_allocate (new_texture, error)) g_clear_pointer (&new_texture, cogl_object_unref); } } cogl_object_unref (bitmap); wl_shm_buffer_end_access (shm_buffer); if (!new_texture) return FALSE; *texture = new_texture; *changed_texture = TRUE; buffer->is_y_inverted = TRUE; return TRUE; }