示例#1
0
gboolean
meta_wayland_egl_stream_attach (MetaWaylandEglStream *stream,
                                GError              **error)
{
  MetaBackend *backend = meta_get_backend ();
  MetaEgl *egl = meta_backend_get_egl (backend);
  ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
  CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
  EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
  EGLint stream_state;

  if (!meta_egl_query_stream (egl, egl_display, stream->egl_stream,
                              EGL_STREAM_STATE_KHR, &stream_state,
                              error))
    return FALSE;

  if (stream_state == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR)
    {
      if (!meta_egl_stream_consumer_acquire (egl, egl_display,
                                             stream->egl_stream,
                                             error))
        return FALSE;
    }

  return TRUE;
}
示例#2
0
gboolean
meta_wayland_buffer_realize (MetaWaylandBuffer *buffer)
{
  EGLint format;
  MetaBackend *backend = meta_get_backend ();
  MetaEgl *egl = meta_backend_get_egl (backend);
  ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
  CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
  EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
#ifdef HAVE_WAYLAND_EGLSTREAM
  MetaWaylandEglStream *stream;
#endif
  MetaWaylandDmaBufBuffer *dma_buf;

  if (wl_shm_buffer_get (buffer->resource) != NULL)
    {
      buffer->type = META_WAYLAND_BUFFER_TYPE_SHM;
      return TRUE;
    }

#ifdef HAVE_WAYLAND_EGLSTREAM
  stream = meta_wayland_egl_stream_new (buffer, NULL);
  if (stream)
    {
      CoglTexture2D *texture;

      texture = meta_wayland_egl_stream_create_texture (stream, NULL);
      if (!texture)
        return FALSE;

      buffer->egl_stream.stream = stream;
      buffer->type = META_WAYLAND_BUFFER_TYPE_EGL_STREAM;
      buffer->egl_stream.texture = COGL_TEXTURE (texture);
      buffer->is_y_inverted = meta_wayland_egl_stream_is_y_inverted (stream);

      return TRUE;
    }
#endif /* HAVE_WAYLAND_EGLSTREAM */

  if (meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
                                     EGL_TEXTURE_FORMAT, &format,
                                     NULL))
    {
      buffer->type = META_WAYLAND_BUFFER_TYPE_EGL_IMAGE;
      return TRUE;
    }

  dma_buf = meta_wayland_dma_buf_from_buffer (buffer);
  if (dma_buf)
    {
      buffer->dma_buf.dma_buf = dma_buf;
      buffer->type = META_WAYLAND_BUFFER_TYPE_DMA_BUF;
      return TRUE;
    }

  return FALSE;
}
示例#3
0
CoglTexture2D *
meta_wayland_egl_stream_create_texture (MetaWaylandEglStream *stream,
                                        GError              **error)
{
  MetaBackend *backend = meta_get_backend ();
  MetaEgl *egl = meta_backend_get_egl (backend);
  ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
  CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
  EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
  CoglTexture2D *texture;
  int width, height;
  int y_inverted;

  if (!meta_egl_query_wayland_buffer (egl, egl_display,
                                      stream->buffer->resource,
                                      EGL_WIDTH, &width,
                                      error))
    return NULL;

  if (!meta_egl_query_wayland_buffer (egl, egl_display,
                                      stream->buffer->resource,
                                      EGL_HEIGHT, &height,
                                      error))
    return NULL;

  if (!meta_egl_query_wayland_buffer (egl, egl_display,
                                      stream->buffer->resource,
                                      EGL_WAYLAND_Y_INVERTED_WL, &y_inverted,
                                      NULL))
    y_inverted = EGL_TRUE;

  texture =
    cogl_texture_2d_new_from_egl_image_external (cogl_context,
                                                 width, height,
                                                 alloc_egl_stream_texture,
                                                 g_object_ref (stream),
                                                 stream_texture_destroyed,
                                                 error);
  if (!texture)
    {
      g_object_unref (stream);
      return NULL;
    }

  if (!cogl_texture_allocate (COGL_TEXTURE (texture), error))
    {
      cogl_object_unref (texture);
      return NULL;
    }

  stream->texture = texture;
  stream->is_y_inverted = !!y_inverted;

  return texture;
}
示例#4
0
static void
meta_wayland_egl_stream_finalize (GObject *object)
{
  MetaWaylandEglStream *stream = META_WAYLAND_EGL_STREAM (object);
  MetaBackend *backend = meta_get_backend ();
  MetaEgl *egl = meta_backend_get_egl (backend);
  ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
  CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
  EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);

  g_assert (!stream->texture);

  meta_egl_destroy_stream (egl, egl_display, stream->egl_stream, NULL);

  G_OBJECT_CLASS (meta_wayland_egl_stream_parent_class)->finalize (object);
}
示例#5
0
static gboolean
alloc_egl_stream_texture (CoglTexture2D *texture,
                          gpointer       user_data,
                          GError       **error)
{
  MetaBackend *backend = meta_get_backend ();
  MetaEgl *egl = meta_backend_get_egl (backend);
  ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
  CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
  EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
  MetaWaylandEglStream *stream = user_data;

  return meta_egl_stream_consumer_gl_texture_external (egl, egl_display,
                                                       stream->egl_stream,
                                                       error);
}
示例#6
0
MetaWaylandEglStream *
meta_wayland_egl_stream_new (MetaWaylandBuffer *buffer,
                             GError           **error)
{
  MetaBackend *backend = meta_get_backend ();
  MetaEgl *egl = meta_backend_get_egl (backend);
  ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
  CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
  EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
  g_autoptr (MetaWaylandEglStream) stream = NULL;
  int stream_fd;
  EGLStreamKHR egl_stream;

  stream = g_object_new (META_TYPE_WAYLAND_EGL_STREAM, NULL);

  /*
   * HACK: Use a (as far as I can tell) undocumented hack by passing
   * EGL_WAYLAND_BUFFER_WL to eglQueryWaylandBufferWL. If it happens to be a
   * dummy EGLStream buffer, we'll get a EGLStream file descriptor.
   *
   * FIXME: At some point, replace this with the EGL_WL_wayland_eglstream
   * extension.
   */
  if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
                                      EGL_WAYLAND_BUFFER_WL, &stream_fd,
                                      error))
    return NULL;

  if (stream_fd == EGL_NO_FILE_DESCRIPTOR_KHR)
    {
      g_set_error (error, G_IO_ERROR,
                   G_IO_ERROR_FAILED,
                   "Stream already used with other wl_buffer");
      return NULL;
    }

  egl_stream = meta_egl_create_stream_from_file_descriptor (egl, egl_display, stream_fd,
                                                            error);
  close (stream_fd);
  if (egl_stream == EGL_NO_STREAM_KHR)
    return NULL;

  stream->egl_stream = egl_stream;
  stream->buffer = buffer;

  return g_steal_pointer (&stream);
}
示例#7
0
gboolean
meta_wayland_is_egl_stream_buffer (MetaWaylandBuffer *buffer)
{
  MetaBackend *backend = meta_get_backend ();
  MetaEgl *egl = meta_backend_get_egl (backend);
  ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
  CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
  EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
  int stream_fd;

  if (!meta_egl_has_extensions (egl, egl_display, NULL,
                                "EGL_KHR_stream_consumer_gltexture",
                                "EGL_KHR_stream_cross_process_fd",
                                NULL))
    return FALSE;

  if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
                                      EGL_WAYLAND_BUFFER_WL, &stream_fd,
                                      NULL))
    return FALSE;

  return TRUE;
}
示例#8
0
static gboolean
egl_image_buffer_attach (MetaWaylandBuffer  *buffer,
                         CoglTexture       **texture,
                         gboolean           *changed_texture,
                         GError            **error)
{
  MetaBackend *backend = meta_get_backend ();
  MetaEgl *egl = meta_backend_get_egl (backend);
  ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend);
  CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
  EGLDisplay egl_display = cogl_egl_context_get_egl_display (cogl_context);
  int format, width, height, y_inverted;
  CoglPixelFormat cogl_format;
  EGLImageKHR egl_image;
  CoglTexture2D *texture_2d;

  if (buffer->egl_image.texture)
    {
      *changed_texture = *texture != buffer->egl_image.texture;
      cogl_clear_object (texture);
      *texture = cogl_object_ref (buffer->egl_image.texture);
      return TRUE;
    }

  if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
                                      EGL_TEXTURE_FORMAT, &format,
                                      error))
    return FALSE;

  if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
                                      EGL_WIDTH, &width,
                                      error))
    return FALSE;

  if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
                                      EGL_HEIGHT, &height,
                                      error))
    return FALSE;

  if (!meta_egl_query_wayland_buffer (egl, egl_display, buffer->resource,
                                      EGL_WAYLAND_Y_INVERTED_WL, &y_inverted,
                                      NULL))
    y_inverted = EGL_TRUE;

  switch (format)
    {
    case EGL_TEXTURE_RGB:
      cogl_format = COGL_PIXEL_FORMAT_RGB_888;
      break;
    case EGL_TEXTURE_RGBA:
      cogl_format = COGL_PIXEL_FORMAT_RGBA_8888_PRE;
      break;
    default:
      g_set_error (error, G_IO_ERROR,
                   G_IO_ERROR_FAILED,
                   "Unsupported buffer format %d", format);
      return FALSE;
    }

  /* The WL_bind_wayland_display spec states that EGL_NO_CONTEXT is to be used
   * in conjunction with the EGL_WAYLAND_BUFFER_WL target. */
  egl_image = meta_egl_create_image (egl, egl_display, EGL_NO_CONTEXT,
                                     EGL_WAYLAND_BUFFER_WL, buffer->resource,
                                     NULL,
                                     error);
  if (egl_image == EGL_NO_IMAGE_KHR)
    return FALSE;

  texture_2d = cogl_egl_texture_2d_new_from_image (cogl_context,
                                                   width, height,
                                                   cogl_format,
                                                   egl_image,
                                                   error);

  meta_egl_destroy_image (egl, egl_display, egl_image, NULL);

  if (!texture_2d)
    return FALSE;

  buffer->egl_image.texture = COGL_TEXTURE (texture_2d);
  buffer->is_y_inverted = !!y_inverted;

  cogl_clear_object (texture);
  *texture = cogl_object_ref (buffer->egl_image.texture);
  *changed_texture = TRUE;

  return TRUE;
}
示例#9
0
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;
}