[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(&region, &box, 1);
+
+    /* See if it's already mapped */
+    if (pixmap->devPrivate.ptr) {
+        if (write)
+            FatalError("attempt to remap buffer as writable");
+        RegionSubtract(&region, &region, &priv->base.pbo_region);
+        if (!RegionNotEmpty(&region))
+            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(&region), RegionNumRects(&region),
+                          off_x, off_y, off_x, off_y, NULL, pixmap->devKind);
+
+    RegionUninit(&region);
+
+    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