aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/glamor/glamor_image.c
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/glamor/glamor_image.c')
-rw-r--r--xorg-server/glamor/glamor_image.c180
1 files changed, 180 insertions, 0 deletions
diff --git a/xorg-server/glamor/glamor_image.c b/xorg-server/glamor/glamor_image.c
new file mode 100644
index 000000000..4791d089f
--- /dev/null
+++ b/xorg-server/glamor/glamor_image.c
@@ -0,0 +1,180 @@
+/*
+ * 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"
+#include "glamor_transform.h"
+
+/*
+ * PutImage. Only does ZPixmap right now as other formats are quite a bit harder
+ */
+
+static Bool
+glamor_put_image_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
+ int w, int h, int leftPad, int format, char *bits)
+{
+ ScreenPtr screen = drawable->pScreen;
+ glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+ PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+ glamor_pixmap_private *pixmap_priv;
+ uint32_t byte_stride = PixmapBytePad(w, drawable->depth);
+ RegionRec region;
+ BoxRec box;
+ int off_x, off_y;
+
+ pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+ return FALSE;
+
+ if (gc->alu != GXcopy)
+ goto bail;
+
+ if (!glamor_pm_is_solid(&pixmap->drawable, gc->planemask))
+ goto bail;
+
+ if (format == XYPixmap && drawable->depth == 1 && leftPad == 0)
+ format = ZPixmap;
+
+ if (format != ZPixmap)
+ goto bail;
+
+ x += drawable->x;
+ y += drawable->y;
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = box.x1 + w;
+ box.y2 = box.y1 + h;
+ RegionInit(&region, &box, 1);
+ RegionIntersect(&region, &region, gc->pCompositeClip);
+
+ glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+ if (off_x || off_y) {
+ x += off_x;
+ y += off_y;
+ RegionTranslate(&region, off_x, off_y);
+ }
+
+ glamor_make_current(glamor_priv);
+
+ glamor_upload_region(pixmap, &region, x, y, (uint8_t *) bits, byte_stride);
+
+ RegionUninit(&region);
+ return TRUE;
+bail:
+ return FALSE;
+}
+
+static void
+glamor_put_image_bail(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
+ int w, int h, int leftPad, int format, char *bits)
+{
+ if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW) &&
+ glamor_prepare_access_gc(gc))
+ fbPutImage(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
+ glamor_finish_access(drawable);
+}
+
+void
+glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
+ int w, int h, int leftPad, int format, char *bits)
+{
+ if (glamor_put_image_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits))
+ return;
+ glamor_put_image_bail(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
+}
+
+Bool
+glamor_put_image_nf(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
+ int w, int h, int leftPad, int format, char *bits)
+{
+ if (glamor_put_image_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits))
+ return TRUE;
+ if (glamor_ddx_fallback_check_pixmap(drawable) &&
+ glamor_ddx_fallback_check_gc(gc))
+ return FALSE;
+ glamor_put_image_bail(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
+ return TRUE;
+}
+
+static Bool
+glamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long plane_mask, char *d)
+{
+ PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
+ glamor_pixmap_private *pixmap_priv;
+ uint32_t byte_stride = PixmapBytePad(w, drawable->depth);
+ BoxRec box;
+ int off_x, off_y;
+
+ pixmap_priv = glamor_get_pixmap_private(pixmap);
+ if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
+ goto bail;
+
+ if (format != ZPixmap || !glamor_pm_is_solid(drawable, plane_mask))
+ goto bail;
+
+ glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
+ box.x1 = x;
+ box.x2 = x + w;
+ box.y1 = y;
+ box.y2 = y + h;
+ glamor_download_boxes(pixmap, &box, 1,
+ drawable->x + off_x, drawable->y + off_y,
+ -x, -y,
+ (uint8_t *) d, byte_stride);
+ return TRUE;
+bail:
+ return FALSE;
+}
+
+static void
+glamor_get_image_bail(DrawablePtr drawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long plane_mask, char *d)
+{
+ if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO))
+ fbGetImage(drawable, x, y, w, h, format, plane_mask, d);
+ glamor_finish_access(drawable);
+}
+
+void
+glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long plane_mask, char *d)
+{
+ if (glamor_get_image_gl(drawable, x, y, w, h, format, plane_mask, d))
+ return;
+ glamor_get_image_bail(drawable, x, y, w, h, format, plane_mask, d);
+}
+
+Bool
+glamor_get_image_nf(DrawablePtr drawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long plane_mask, char *d)
+{
+ if (glamor_get_image_gl(drawable, x, y, w, h, format, plane_mask, d))
+ return TRUE;
+
+ if (glamor_ddx_fallback_check_pixmap(drawable))
+ return FALSE;
+
+ glamor_get_image_bail(drawable, x, y, w, h, format, plane_mask, d);
+ return TRUE;
+}