[PATCH 07/20] glamor: Add simple upload/download functions in glamor_transfer

Keith Packard keithp at keithp.com
Tue Mar 18 22:09:41 PDT 2014


These use glTexSubimage2D for upload and glReadPixels for
download. There are a variety of interfaces to the basic function as
needed by the callers.

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 glamor/Makefile.am       |   2 +
 glamor/glamor_transfer.c | 260 +++++++++++++++++++++++++++++++++++++++++++++++
 glamor/glamor_transfer.h |  55 ++++++++++
 3 files changed, 317 insertions(+)
 create mode 100644 glamor/glamor_transfer.c
 create mode 100644 glamor/glamor_transfer.h

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index dec6467..9544923 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -23,6 +23,8 @@ libglamor_la_SOURCES = \
 	glamor_render.c \
 	glamor_gradient.c \
 	glamor_program.c \
+	glamor_transfer.c \
+	glamor_transfer.h \
 	glamor_transform.c \
 	glamor_trapezoid.c \
 	glamor_tile.c \
diff --git a/glamor/glamor_transfer.c b/glamor/glamor_transfer.c
new file mode 100644
index 0000000..d25c659
--- /dev/null
+++ b/glamor/glamor_transfer.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "glamor_priv.h"
+#include "glamor_transfer.h"
+
+/* XXX a kludge for now */
+void
+glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type)
+{
+    switch (pixmap->drawable.depth) {
+    case 24:
+    case 32:
+        *format = GL_BGRA;
+        *type = GL_UNSIGNED_INT_8_8_8_8_REV;
+        break;
+    case 16:
+        *format = GL_RGB;
+        *type = GL_UNSIGNED_SHORT_5_6_5;
+        break;
+    case 15:
+        *format = GL_BGRA;
+        *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+        break;
+    case 8:
+        *format = GL_ALPHA;
+        *type = GL_UNSIGNED_BYTE;
+        break;
+    default:
+        FatalError("Invalid pixmap depth %d\n", pixmap->drawable.depth);
+        break;
+    }
+}
+
+/*
+ * Write a region of bits into a pixmap
+ */
+void
+glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                    int dx_src, int dy_src,
+                    int dx_dst, int dy_dst,
+                    uint8_t *bits, uint32_t byte_stride)
+{
+    ScreenPtr                   screen = pixmap->drawable.pScreen;
+    glamor_screen_private       *glamor_priv = glamor_get_screen_private(screen);
+    glamor_pixmap_private       *priv = glamor_get_pixmap_private(pixmap);
+    int                         box_x, box_y;
+    int                         bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
+    GLenum                      type;
+    GLenum                      format;
+
+    glamor_format_for_pixmap(pixmap, &format, &type);
+
+    glamor_get_context(glamor_priv);
+
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
+
+    glamor_pixmap_loop(priv, box_x, box_y) {
+        BoxPtr                  box = glamor_pixmap_box_at(priv, box_x, box_y);
+        glamor_pixmap_fbo       *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y);
+        BoxPtr                  boxes = in_boxes;
+        int                     nbox = in_nbox;
+
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, fbo->tex);
+
+        while (nbox--) {
+
+            /* compute drawable coordinates */
+            int x1 = boxes->x1 + dx_dst;
+            int x2 = boxes->x2 + dx_dst;
+            int y1 = boxes->y1 + dy_dst;
+            int y2 = boxes->y2 + dy_dst;
+
+            if (x1 < box->x1)
+                x1 = box->x1;
+            if (box->x2 < x2)
+                x2 = box->x2;
+
+            if (x2 <= x1)
+                continue;
+
+            if (y1 < box->y1)
+                y1 = box->y1;
+            if (box->y2 < y2)
+                y2 = box->y2;
+
+            if (y2 <= y1)
+                continue;
+
+            glPixelStorei(GL_UNPACK_SKIP_ROWS, y1 - dy_dst + dy_src);
+            glPixelStorei(GL_UNPACK_SKIP_PIXELS, x1 - dx_dst + dx_src);
+
+            glTexSubImage2D(GL_TEXTURE_2D, 0,
+                            x1 - box->x1, y1 - box->y1,
+                            x2 - x1, y2 - y1,
+                            format, type,
+                            bits);
+        }
+    }
+
+    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+    glamor_put_context(glamor_priv);
+}
+
+/*
+ * Upload a region of data
+ */
+
+void
+glamor_upload_region(PixmapPtr pixmap, RegionPtr region,
+                     int region_x, int region_y,
+                     uint8_t *bits, uint32_t byte_stride)
+{
+    glamor_upload_boxes(pixmap, RegionRects(region), RegionNumRects(region),
+                        -region_x, -region_y,
+                        0, 0,
+                        bits, byte_stride);
+}
+
+/*
+ * Take the data in the pixmap and stuff it back into the FBO
+ */
+void
+glamor_upload_pixmap(PixmapPtr pixmap)
+{
+    BoxRec box;
+
+    box.x1 = 0;
+    box.x2 = pixmap->drawable.width;
+    box.y1 = 0;
+    box.y2 = pixmap->drawable.height;
+    glamor_upload_boxes(pixmap, &box, 1, 0, 0, 0, 0,
+                        pixmap->devPrivate.ptr, pixmap->devKind);
+}
+
+/*
+ * Read stuff from the pixmap FBOs and write to memory
+ */
+void
+glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                      int dx_src, int dy_src,
+                      int dx_dst, int dy_dst,
+                      uint8_t *bits, uint32_t byte_stride)
+{
+    ScreenPtr screen = pixmap->drawable.pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
+    int box_x, box_y;
+    int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
+    GLenum type;
+    GLenum format;
+
+    glamor_format_for_pixmap(pixmap, &format, &type);
+
+    glamor_get_context(glamor_priv);
+
+    glPixelStorei(GL_PACK_ALIGNMENT, 4);
+    glPixelStorei(GL_PACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
+
+    glamor_pixmap_loop(priv, box_x, box_y) {
+        BoxPtr                  box = glamor_pixmap_box_at(priv, box_x, box_y);
+        glamor_pixmap_fbo       *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y);
+        BoxPtr                  boxes = in_boxes;
+        int                     nbox = in_nbox;
+
+        glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->fb);
+
+        while (nbox--) {
+
+            /* compute drawable coordinates */
+            int                     x1 = boxes->x1 + dx_src;
+            int                     x2 = boxes->x2 + dx_src;
+            int                     y1 = boxes->y1 + dy_src;
+            int                     y2 = boxes->y2 + dy_src;
+
+            if (x1 < box->x1)
+                x1 = box->x1;
+            if (box->x2 < x2)
+                x2 = box->x2;
+
+            if (y1 < box->y1)
+                y1 = box->y1;
+            if (box->y2 < y2)
+                y2 = box->y2;
+
+            if (x2 <= x1)
+                continue;
+            if (y2 <= y1)
+                continue;
+
+            glPixelStorei(GL_PACK_SKIP_PIXELS, x1 - dx_src + dx_dst);
+            glPixelStorei(GL_PACK_SKIP_ROWS, y1 - dy_src + dy_dst);
+            glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, format, type, bits);
+        }
+    }
+    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
+    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
+    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+    glamor_put_context(glamor_priv);
+}
+
+/*
+ * Read data from the pixmap FBO
+ */
+void
+glamor_download_rect(PixmapPtr pixmap, int x, int y, int w, int h, uint8_t *bits)
+{
+    BoxRec      box;
+
+    box.x1 = x;
+    box.x2 = x + w;
+    box.y1 = y;
+    box.y2 = y + h;
+
+    glamor_download_boxes(pixmap, &box, 1, 0, 0, -x, -y,
+                          bits, PixmapBytePad(w, pixmap->drawable.depth));
+}
+
+/*
+ * Pull the data from the FBO down to the pixmap
+ */
+void
+glamor_download_pixmap(PixmapPtr pixmap)
+{
+    BoxRec      box;
+
+    box.x1 = 0;
+    box.x2 = pixmap->drawable.width;
+    box.y1 = 0;
+    box.y2 = pixmap->drawable.height;
+
+    glamor_download_boxes(pixmap, &box, 1, 0, 0, 0, 0,
+                          pixmap->devPrivate.ptr, pixmap->devKind);
+}
diff --git a/glamor/glamor_transfer.h b/glamor/glamor_transfer.h
new file mode 100644
index 0000000..de8186a
--- /dev/null
+++ b/glamor/glamor_transfer.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2014 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifndef _GLAMOR_TRANSFER_H_
+#define _GLAMOR_TRANSFER_H_
+
+void
+glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type);
+
+void
+glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                    int dx_src, int dy_src,
+                    int dx_dst, int dy_dst,
+                    uint8_t *bits, uint32_t byte_stride);
+
+void
+glamor_upload_region(PixmapPtr pixmap, RegionPtr region,
+                     int region_x, int region_y,
+                     uint8_t *bits, uint32_t byte_stride);
+
+void
+glamor_upload_pixmap(PixmapPtr pixmap);
+
+void
+glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
+                      int dx_src, int dy_src,
+                      int dx_dst, int dy_dst,
+                      uint8_t *bits, uint32_t byte_stride);
+
+void
+glamor_download_rect(PixmapPtr pixmap, int x, int y, int w, int h, uint8_t *bits);
+
+void
+glamor_download_pixmap(PixmapPtr pixmap);
+
+#endif /* _GLAMOR_TRANSFER_H_ */
-- 
1.9.0



More information about the xorg-devel mailing list