gl-renderer: introduce struct egl_image
authorLouis-Francis Ratté-Boulianne <lfrb@collabora.com>
Mon, 8 Jun 2015 13:37:05 +0000 (16:37 +0300)
committerPekka Paalanen <pekka.paalanen@collabora.co.uk>
Fri, 14 Aug 2015 12:53:25 +0000 (15:53 +0300)
This is a reference-counted holder of an EGLImage. For now, direct
EGLImage usage is simply converted to use egl_image. Use of reference
counting will come in a later patch.

v2:
- this is a new patch, split from gl-renderer dmabuf import support

Signed-off-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
Reviewed-by: Daniel Stone <daniels@collabora.com>
src/gl-renderer.c

index 88db26b..4c7137d 100644 (file)
@@ -90,6 +90,14 @@ enum buffer_type {
        BUFFER_TYPE_EGL
 };
 
+struct gl_renderer;
+
+struct egl_image {
+       struct gl_renderer *renderer;
+       EGLImageKHR image;
+       int refcount;
+};
+
 struct gl_surface_state {
        GLfloat color[4];
        struct gl_shader *shader;
@@ -105,7 +113,7 @@ struct gl_surface_state {
        GLenum gl_format;
        GLenum gl_pixel_type;
 
-       EGLImageKHR images[3];
+       struct egl_image* images[3];
        GLenum target;
        int num_images;
 
@@ -197,6 +205,51 @@ get_renderer(struct weston_compositor *ec)
        return (struct gl_renderer *)ec->renderer;
 }
 
+static struct egl_image*
+egl_image_create(struct gl_renderer *gr, EGLenum target,
+                EGLClientBuffer buffer, const EGLint *attribs)
+{
+       struct egl_image *img;
+
+       img = zalloc(sizeof *img);
+       img->renderer = gr;
+       img->refcount = 1;
+       img->image = gr->create_image(gr->egl_display, EGL_NO_CONTEXT,
+                                     target, buffer, attribs);
+
+       if (img->image == EGL_NO_IMAGE_KHR) {
+               free(img);
+               return NULL;
+       }
+
+       return img;
+}
+
+static struct egl_image*
+egl_image_ref(struct egl_image *image)
+{
+       image->refcount++;
+
+       return image;
+}
+
+static int
+egl_image_unref(struct egl_image *image)
+{
+       struct gl_renderer *gr = image->renderer;
+
+       assert(image->refcount > 0);
+
+       image->refcount--;
+       if (image->refcount > 0)
+               return image->refcount;
+
+       gr->destroy_image(gr->egl_display, image->image);
+       free(image);
+
+       return 0;
+}
+
 static const char *
 egl_error_string(EGLint code)
 {
@@ -1290,8 +1343,10 @@ gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
        gr->query_buffer(gr->egl_display, buffer->legacy_buffer,
                         EGL_WAYLAND_Y_INVERTED_WL, &buffer->y_inverted);
 
-       for (i = 0; i < gs->num_images; i++)
-               gr->destroy_image(gr->egl_display, gs->images[i]);
+       for (i = 0; i < gs->num_images; i++) {
+               egl_image_unref(gs->images[i]);
+               gs->images[i] = NULL;
+       }
        gs->num_images = 0;
        gs->target = GL_TEXTURE_2D;
        switch (format) {
@@ -1325,8 +1380,7 @@ gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
                attribs[0] = EGL_WAYLAND_PLANE_WL;
                attribs[1] = i;
                attribs[2] = EGL_NONE;
-               gs->images[i] = gr->create_image(gr->egl_display,
-                                                NULL,
+               gs->images[i] = egl_image_create(gr,
                                                 EGL_WAYLAND_BUFFER_WL,
                                                 buffer->legacy_buffer,
                                                 attribs);
@@ -1339,7 +1393,7 @@ gl_renderer_attach_egl(struct weston_surface *es, struct weston_buffer *buffer,
                glActiveTexture(GL_TEXTURE0 + i);
                glBindTexture(gs->target, gs->textures[i]);
                gr->image_target_texture_2d(gs->target,
-                                           gs->images[i]);
+                                           gs->images[i]->image);
        }
 
        gs->pitch = buffer->width;
@@ -1362,7 +1416,7 @@ gl_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer)
 
        if (!buffer) {
                for (i = 0; i < gs->num_images; i++) {
-                       gr->destroy_image(gr->egl_display, gs->images[i]);
+                       egl_image_unref(gs->images[i]);
                        gs->images[i] = NULL;
                }
                gs->num_images = 0;
@@ -1564,7 +1618,7 @@ surface_state_destroy(struct gl_surface_state *gs, struct gl_renderer *gr)
        glDeleteTextures(gs->num_textures, gs->textures);
 
        for (i = 0; i < gs->num_images; i++)
-               gr->destroy_image(gr->egl_display, gs->images[i]);
+               egl_image_unref(gs->images[i]);
 
        weston_buffer_reference(&gs->buffer_ref, NULL);
        pixman_region32_fini(&gs->texture_damage);