static ClutterStageWaylandWaylandBuffer * wayland_create_drm_buffer (ClutterBackendWayland *backend_wayland, ClutterGeometry *geom) { EGLDisplay edpy = clutter_wayland_get_egl_display (); struct wl_visual *visual; EGLint name, stride; ClutterStageWaylandWaylandBufferDRM *buffer; EGLint image_attribs[] = { EGL_WIDTH, 0, EGL_HEIGHT, 0, EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA, EGL_NONE }; buffer = g_slice_new (ClutterStageWaylandWaylandBufferDRM); buffer->buffer.type = BUFFER_TYPE_DRM; image_attribs[1] = geom->width; image_attribs[3] = geom->height; buffer->drm_image = backend_wayland->create_drm_image (edpy, image_attribs); glGenTextures (1, &buffer->texture); glBindTexture (GL_TEXTURE_2D, buffer->texture); backend_wayland->image_target_texture_2d (GL_TEXTURE_2D, buffer->drm_image); buffer->buffer.tex = cogl_texture_new_from_foreign (buffer->texture, GL_TEXTURE_2D, geom->width, geom->height, 0, 0, VISUAL_ARGB_PRE); backend_wayland->export_drm_image (edpy, buffer->drm_image, &name, NULL, &stride); visual = get_visual (backend_wayland->wayland_display, VISUAL_ARGB_PRE); buffer->buffer.wayland_buffer = wl_drm_create_buffer (backend_wayland->wayland_drm, name, geom->width, geom->height, stride, visual); return &buffer->buffer; }
static void test_coglbox_init (TestCoglbox *self) { TestCoglboxPrivate *priv; guchar data[12]; self->priv = priv = TEST_COGLBOX_GET_PRIVATE(self); /* Prepare a 2x2 pixels texture */ data[0] = 255; data[1] = 0; data[2] = 0; data[3] = 0; data[4] = 255; data[5] = 0; data[6] = 0; data[7] = 0; data[8] = 255; data[9] = 0; data[10] = 0; data[11] = 0; glGenTextures (1, &priv->gl_handle); glBindTexture (GL_TEXTURE_2D, priv->gl_handle); glPixelStorei (GL_UNPACK_ALIGNMENT, 1); glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, data); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); /* Create texture from foreign */ priv->cogl_handle = cogl_texture_new_from_foreign (priv->gl_handle, GL_TEXTURE_2D, 2, 2, 0, 0, COGL_PIXEL_FORMAT_RGB_888); if (priv->cogl_handle == COGL_INVALID_HANDLE) { printf ("Failed creating texture from foreign!\n"); return; } }
/* put a gst gl buffer in the texture actor */ gboolean update_texture_actor (gpointer data) { ClutterTexture *texture_actor = (ClutterTexture *) data; GAsyncQueue *queue_input_buf = g_object_get_data (G_OBJECT (texture_actor), "queue_input_buf"); GAsyncQueue *queue_output_buf = g_object_get_data (G_OBJECT (texture_actor), "queue_output_buf"); GstGLBuffer *gst_gl_buf = g_async_queue_pop (queue_input_buf); ClutterActor *stage = g_object_get_data (G_OBJECT (texture_actor), "stage"); CoglHandle cogl_texture = 0; /* Create a cogl texture from the gst gl texture */ glEnable (GL_TEXTURE_RECTANGLE_ARB); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, gst_gl_buf->texture); if (glGetError () != GL_NO_ERROR) g_debug ("failed to bind texture that comes from gst-gl\n"); cogl_texture = cogl_texture_new_from_foreign (gst_gl_buf->texture, CGL_TEXTURE_RECTANGLE_ARB, gst_gl_buf->width, gst_gl_buf->height, 0, 0, COGL_PIXEL_FORMAT_RGBA_8888); glBindTexture (GL_TEXTURE_RECTANGLE_ARB, 0); /* Previous cogl texture is replaced and so its ref counter discreases to 0. * According to the source code, glDeleteTexture is not called when the previous * ref counter of the previous cogl texture is reaching 0 because is_foreign is TRUE */ clutter_texture_set_cogl_texture (CLUTTER_TEXTURE (texture_actor), cogl_texture); cogl_texture_unref (cogl_texture); /* we can now show the clutter scene if not yet visible */ if (!CLUTTER_ACTOR_IS_VISIBLE (stage)) clutter_actor_show_all (stage); /* push buffer so it can be unref later */ g_async_queue_push (queue_output_buf, gst_gl_buf); return FALSE; }
CoglHandle meta_texture_rectangle_new (unsigned int width, unsigned int height, CoglTextureFlags flags, CoglPixelFormat format, GLenum internal_gl_format, GLenum internal_format, unsigned int rowstride, const guint8 *data) { CoglHandle cogl_tex = COGL_INVALID_HANDLE; #ifdef GL_TEXTURE_RECTANGLE_ARB static CoglUserDataKey user_data_key; GLint old_binding; GLuint tex; if (pf_glGenTextures == NULL) { pf_glGetIntegerv = (void *) cogl_get_proc_address ("glGetIntegerv"); pf_glTexImage2D = (void *) cogl_get_proc_address ("glTexImage2D"); pf_glGenTextures = (void *) cogl_get_proc_address ("glGenTextures"); pf_glDeleteTextures = (void *) cogl_get_proc_address ("glDeleteTextures"); pf_glBindTexture = (void *) cogl_get_proc_address ("glBindTexture"); } pf_glGenTextures (1, &tex); pf_glGetIntegerv (GL_TEXTURE_BINDING_RECTANGLE_ARB, &old_binding); pf_glBindTexture (GL_TEXTURE_RECTANGLE_ARB, tex); pf_glTexImage2D (GL_TEXTURE_RECTANGLE_ARB, 0, internal_gl_format, width, height, 0, internal_gl_format, GL_UNSIGNED_BYTE, NULL); pf_glBindTexture (GL_TEXTURE_RECTANGLE_ARB, old_binding); cogl_tex = cogl_texture_new_from_foreign (tex, GL_TEXTURE_RECTANGLE_ARB, width, height, 0, 0, /* no waste */ internal_format); /* Cogl won't destroy the GL texture when a foreign texture is used so we need to destroy it manually. We can set a destroy notification callback to do this transparently */ cogl_object_set_user_data (cogl_tex, &user_data_key, GUINT_TO_POINTER (tex), rectangle_texture_destroy_cb); /* Use cogl_texture_set_region instead of uploading the data directly with GL calls so that we can let Cogl deal with setting the pixel store parameters and handling format conversion */ if (data) cogl_texture_set_region (cogl_tex, 0, 0, /* src x/y */ 0, 0, /* dst x/y */ width, height, /* dst width/height */ width, height, /* src width/height */ format, rowstride, data); #endif /* GL_TEXTURE_RECTANGLE_ARB */ return cogl_tex; }