diff options
Diffstat (limited to 'xorg-server/glamor/glamor_image.c')
-rw-r--r-- | xorg-server/glamor/glamor_image.c | 180 |
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(®ion, &box, 1); + RegionIntersect(®ion, ®ion, gc->pCompositeClip); + + glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); + if (off_x || off_y) { + x += off_x; + y += off_y; + RegionTranslate(®ion, off_x, off_y); + } + + glamor_make_current(glamor_priv); + + glamor_upload_region(pixmap, ®ion, x, y, (uint8_t *) bits, byte_stride); + + RegionUninit(®ion); + 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; +} |