compositor: make GL_EXT_read_format_bgra optional
authorPekka Paalanen <ppaalanen@gmail.com>
Tue, 17 Apr 2012 12:02:08 +0000 (15:02 +0300)
committerPekka Paalanen <ppaalanen@gmail.com>
Tue, 17 Apr 2012 12:12:17 +0000 (15:12 +0300)
Some GL implementations do not provide GL_EXT_read_format_bgra
extension.

Set a glReadPixels format based on whether the extensions is supported
or not, and use that format in all backends.

Add RGBA->BGRA swapping copy to screenshooter to keep the shm buffer
data format as BGRA.

Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
src/compositor-drm.c
src/compositor-wayland.c
src/compositor-x11.c
src/compositor.c
src/compositor.h
src/screenshooter.c

index 1b0fbd0..d2a2ea1 100644 (file)
@@ -1052,8 +1052,9 @@ drm_output_read_pixels(struct weston_output *output_base, void *data)
        eglMakeCurrent(compositor->base.display, output->egl_surface,
                        output->egl_surface, compositor->base.context);
 
-       glReadPixels(0, 0, output_base->current->width, output_base->current->height,
-                               GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
+       glReadPixels(0, 0, output_base->current->width,
+                    output_base->current->height,
+                    compositor->base.read_format, GL_UNSIGNED_BYTE, data);
 }
 
 static int
index 7a9ebde..c9d599d 100644 (file)
@@ -387,8 +387,9 @@ wayland_output_read_pixels(struct weston_output *output_base, void *data)
        eglMakeCurrent(compositor->base.display, output->egl_surface,
                        output->egl_surface, compositor->base.context);
 
-       glReadPixels(0, 0, output_base->current->width, output_base->current->height,
-                               GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
+       glReadPixels(0, 0, output_base->current->width,
+                    output_base->current->height,
+                    compositor->base.read_format, GL_UNSIGNED_BYTE, data);
 }
 
 static int
index 9822c2c..4361a01 100644 (file)
@@ -354,8 +354,9 @@ x11_output_read_pixels(struct weston_output *output_base, void *data)
        eglMakeCurrent(compositor->base.display, output->egl_surface,
                        output->egl_surface, compositor->base.context);
 
-       glReadPixels(0, 0, output_base->current->width, output_base->current->height,
-                               GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
+       glReadPixels(0, 0, output_base->current->width,
+                    output_base->current->height,
+                    compositor->base.read_format, GL_UNSIGNED_BYTE, data);
 }
 
 static int
index ac5e91c..17daac4 100644 (file)
@@ -2391,10 +2391,10 @@ weston_compositor_init(struct weston_compositor *ec, struct wl_display *display)
                return -1;
        }
 
-       if (!strstr(extensions, "GL_EXT_read_format_bgra")) {
-               fprintf(stderr, "GL_EXT_read_format_bgra not available\n");
-               return -1;
-       }
+       if (strstr(extensions, "GL_EXT_read_format_bgra"))
+               ec->read_format = GL_BGRA_EXT;
+       else
+               ec->read_format = GL_RGBA;
 
        if (strstr(extensions, "GL_EXT_unpack_subimage"))
                ec->has_unpack_subimage = 1;
index e381e66..93284c5 100644 (file)
@@ -223,6 +223,7 @@ struct weston_compositor {
        PFNEGLDESTROYIMAGEKHRPROC destroy_image;
 
        int has_unpack_subimage;
+       GLenum read_format;
 
        PFNEGLBINDWAYLANDDISPLAYWL bind_display;
        PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
index 835e175..b4b341b 100644 (file)
@@ -51,6 +51,37 @@ copy_bgra_yflip(uint8_t *dst, uint8_t *src, int height,
 }
 
 static void
+copy_row_swap_RB(void *vdst, void *vsrc, int bytes)
+{
+       uint32_t *dst = vdst;
+       uint32_t *src = vsrc;
+       uint32_t *end = dst + bytes / 4;
+
+       while (dst < end) {
+               uint32_t v = *src++;
+               /*                    A R G B */
+               uint32_t tmp = v & 0xff00ff00;
+               tmp |= (v >> 16) & 0x000000ff;
+               tmp |= (v << 16) & 0x00ff0000;
+               *dst++ = tmp;
+       }
+}
+
+static void
+copy_rgba_yflip(uint8_t *dst, uint8_t *src, int height,
+               int dst_stride, int src_stride)
+{
+       uint8_t *end;
+
+       end = dst + height * dst_stride;
+       while (dst < end) {
+               copy_row_swap_RB(dst, src, src_stride);
+               dst += dst_stride;
+               src -= src_stride;
+       }
+}
+
+static void
 screenshooter_shoot(struct wl_client *client,
                    struct wl_resource *resource,
                    struct wl_resource *output_resource,
@@ -82,8 +113,19 @@ screenshooter_shoot(struct wl_client *client,
        d = wl_shm_buffer_get_data(buffer) + output->y * buffer_stride +
                                                        output->x * 4;
        s = tmp + output_stride * (output->current->height - 1);
-       copy_bgra_yflip(d, s, output->current->height,
-                       buffer_stride, output_stride);
+
+       switch (output->compositor->read_format) {
+       case GL_BGRA_EXT:
+               copy_bgra_yflip(d, s, output->current->height,
+                               buffer_stride, output_stride);
+               break;
+       case GL_RGBA:
+               copy_rgba_yflip(d, s, output->current->height,
+                               buffer_stride, output_stride);
+               break;
+       default:
+               break;
+       }
 
        free(tmp);
 }