[PATCH 08/20] glamor: Add new path for migrating pixmaps in/out of CPU memory
Keith Packard
keithp at keithp.com
Tue Mar 18 22:09:42 PDT 2014
I couldn't get the existing paths to work and they made no sense, so I
just wrote new ones.
Signed-off-by: Keith Packard <keithp at keithp.com>
---
glamor/Makefile.am | 2 +
glamor/glamor_prepare.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++
glamor/glamor_prepare.h | 38 +++++++++++
glamor/glamor_priv.h | 2 +
4 files changed, 209 insertions(+)
create mode 100644 glamor/glamor_prepare.c
create mode 100644 glamor/glamor_prepare.h
diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 9544923..361c0d6 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -22,6 +22,8 @@ libglamor_la_SOURCES = \
glamor_setspans.c \
glamor_render.c \
glamor_gradient.c \
+ glamor_prepare.c \
+ glamor_prepare.h \
glamor_program.c \
glamor_transfer.c \
glamor_transfer.h \
diff --git a/glamor/glamor_prepare.c b/glamor/glamor_prepare.c
new file mode 100644
index 0000000..a653572
--- /dev/null
+++ b/glamor/glamor_prepare.c
@@ -0,0 +1,167 @@
+/*
+ * 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_prepare.h"
+#include "glamor_transfer.h"
+
+/*
+ * Make a drawable ready to draw with fb by
+ * creating a PBO large enough for the whole object
+ * and downloading all of the FBOs into it.
+ */
+
+Bool
+glamor_prep_drawable(DrawablePtr drawable, Bool write)
+{
+ PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+ glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
+ int gl_access, gl_usage;
+ RegionRec region;
+ BoxRec box;
+ int off_x, off_y;
+
+ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv))
+ return TRUE;
+
+ box.x1 = drawable->x;
+ box.x2 = box.x1 + drawable->width;
+ box.y1 = drawable->y;
+ box.y2 = box.y1 + drawable->height;
+
+ RegionInit(®ion, &box, 1);
+
+ /* See if it's already mapped */
+ if (pixmap->devPrivate.ptr) {
+ if (write)
+ FatalError("attempt to remap buffer as writable");
+ RegionSubtract(®ion, ®ion, &priv->base.pbo_region);
+ if (!RegionNotEmpty(®ion))
+ return TRUE;
+
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->base.pbo);
+ glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
+
+ } else {
+ RegionInit(&priv->base.pbo_region, &box, 1);
+
+ if (priv->base.pbo == 0)
+ glGenBuffers(1, &priv->base.pbo);
+
+ if (write)
+ gl_usage = GL_DYNAMIC_DRAW;
+ else
+ gl_usage = GL_STREAM_READ;
+
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, priv->base.pbo);
+ glBufferData(GL_PIXEL_PACK_BUFFER, pixmap->devKind * pixmap->drawable.height, NULL, gl_usage);
+ priv->base.map_access = write ? GLAMOR_ACCESS_RW : GLAMOR_ACCESS_RO;
+ }
+
+ glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+
+ glamor_download_boxes(pixmap, RegionRects(®ion), RegionNumRects(®ion),
+ off_x, off_y, off_x, off_y, NULL, pixmap->devKind);
+
+ RegionUninit(®ion);
+
+ if (priv->base.map_access == GLAMOR_ACCESS_RW)
+ gl_access = GL_READ_WRITE;
+ else
+ gl_access = GL_READ_ONLY;
+
+ pixmap->devPrivate.ptr = glMapBuffer(GL_PIXEL_PACK_BUFFER, gl_access);
+ glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
+
+ return TRUE;
+}
+
+/*
+ * When we're done with the drawable, unmap the PBO, reupload
+ * if we were writing to it and then unbind it to release the memory
+ */
+
+void
+glamor_fini_drawable(DrawablePtr drawable)
+{
+ PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+ glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
+
+ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(priv))
+ return;
+
+ if (!pixmap->devPrivate.ptr)
+ return;
+
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, priv->base.pbo);
+ glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+ pixmap->devPrivate.ptr = NULL;
+
+ if (priv->base.map_access == GLAMOR_ACCESS_RW) {
+ int off_x, off_y;
+
+ glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+
+ glamor_upload_boxes(pixmap, RegionRects(&priv->base.pbo_region), RegionNumRects(&priv->base.pbo_region),
+ off_x, off_y, off_x, off_y, NULL, pixmap->devKind);
+ }
+
+ RegionUninit(&priv->base.pbo_region);
+
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+}
+
+/*
+ * Make a GC ready to use with fb. This just
+ * means making sure the appropriate fill pixmap is
+ * in CPU memory again
+ */
+
+Bool
+glamor_prep_gc(GCPtr gc)
+{
+ switch (gc->fillStyle) {
+ case FillTiled:
+ return glamor_prep_drawable(&gc->tile.pixmap->drawable, FALSE);
+ case FillStippled:
+ case FillOpaqueStippled:
+ return glamor_prep_drawable(&gc->stipple->drawable, FALSE);
+ }
+ return TRUE;
+}
+
+/*
+ * Free any temporary CPU pixmaps for the GC
+ */
+void
+glamor_fini_gc(GCPtr gc)
+{
+ switch (gc->fillStyle) {
+ case FillTiled:
+ glamor_fini_drawable(&gc->tile.pixmap->drawable);
+ break;
+ case FillStippled:
+ case FillOpaqueStippled:
+ glamor_fini_drawable(&gc->stipple->drawable);
+ break;
+ }
+}
diff --git a/glamor/glamor_prepare.h b/glamor/glamor_prepare.h
new file mode 100644
index 0000000..70ecc4a
--- /dev/null
+++ b/glamor/glamor_prepare.h
@@ -0,0 +1,38 @@
+/*
+ * 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_PREPARE_H_
+#define _GLAMOR_PREPARE_H_
+
+Bool
+glamor_prep_drawable(DrawablePtr drawable, Bool write);
+
+void
+glamor_fini_drawable(DrawablePtr drawable);
+
+Bool
+glamor_prep_gc(GCPtr gc);
+
+void
+glamor_fini_gc(GCPtr gc);
+
+#endif /* _GLAMOR_PREPARE_H_ */
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 5013799..1f6df3d 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -419,6 +419,8 @@ typedef struct glamor_pixmap_private_base {
int drm_stride;
glamor_screen_private *glamor_priv;
PicturePtr picture;
+ GLuint pbo;
+ RegionRec pbo_region;
#if GLAMOR_HAS_GBM
EGLImageKHR image;
#endif
--
1.9.0
More information about the xorg-devel
mailing list