summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2014-04-01 21:15:43 -0700
committerKeith Packard <keithp@keithp.com>2014-04-03 13:07:51 -0700
commitd78c257f523908760c1b872cc4bef3d42eb31f50 (patch)
treef59ef06cdb58fb21871e8b9b94e3cc5fc2a5fb47
parent693e6bea897e4c9473a9f22dd8b90df3437e04a1 (diff)
glamor: Add simple upload/download functions in glamor_transfer
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@keithp.com> Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--glamor/Makefile.am2
-rw-r--r--glamor/glamor_transfer.c264
-rw-r--r--glamor/glamor_transfer.h55
3 files changed, 321 insertions, 0 deletions
diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 8555e4087..3664fd380 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -24,6 +24,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 000000000..0378bb076
--- /dev/null
+++ b/glamor/glamor_transfer.c
@@ -0,0 +1,264 @@
+/*
+ * 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;
+
+ boxes++;
+
+ 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;
+
+ boxes++;
+
+ 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 000000000..de8186a70
--- /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_ */