1/* 2 * Copyright © 2014 Keith Packard 3 * 4 * Permission to use, copy, modify, distribute, and sell this software and its 5 * documentation for any purpose is hereby granted without fee, provided that 6 * the above copyright notice appear in all copies and that both that copyright 7 * notice and this permission notice appear in supporting documentation, and 8 * that the name of the copyright holders not be used in advertising or 9 * publicity pertaining to distribution of the software without specific, 10 * written prior permission. The copyright holders make no representations 11 * about the suitability of this software for any purpose. It is provided "as 12 * is" without express or implied warranty. 13 * 14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20 * OF THIS SOFTWARE. 21 */ 22 23#include "glamor_priv.h" 24#include "glamor_transfer.h" 25#include "glamor_transform.h" 26 27/* 28 * PutImage. Only does ZPixmap right now as other formats are quite a bit harder 29 */ 30 31static Bool 32glamor_put_image_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, 33 int w, int h, int leftPad, int format, char *bits) 34{ 35 ScreenPtr screen = drawable->pScreen; 36 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 37 PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); 38 glamor_pixmap_private *pixmap_priv; 39 uint32_t byte_stride = PixmapBytePad(w, drawable->depth); 40 RegionRec region; 41 BoxRec box; 42 int off_x, off_y; 43 44 pixmap_priv = glamor_get_pixmap_private(pixmap); 45 46 if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) 47 return FALSE; 48 49 if (gc->alu != GXcopy) 50 goto bail; 51 52 if (!glamor_pm_is_solid(gc->depth, gc->planemask)) 53 goto bail; 54 55 if (format == XYPixmap && drawable->depth == 1 && leftPad == 0) 56 format = ZPixmap; 57 58 if (format != ZPixmap) 59 goto bail; 60 61 x += drawable->x; 62 y += drawable->y; 63 box.x1 = x; 64 box.y1 = y; 65 box.x2 = box.x1 + w; 66 box.y2 = box.y1 + h; 67 RegionInit(®ion, &box, 1); 68 RegionIntersect(®ion, ®ion, gc->pCompositeClip); 69 70 glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); 71 if (off_x || off_y) { 72 x += off_x; 73 y += off_y; 74 RegionTranslate(®ion, off_x, off_y); 75 } 76 77 glamor_make_current(glamor_priv); 78 79 glamor_upload_region(pixmap, ®ion, x, y, (uint8_t *) bits, byte_stride); 80 81 RegionUninit(®ion); 82 return TRUE; 83bail: 84 return FALSE; 85} 86 87static void 88glamor_put_image_bail(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, 89 int w, int h, int leftPad, int format, char *bits) 90{ 91 if (glamor_prepare_access_box(drawable, GLAMOR_ACCESS_RW, x, y, w, h)) 92 fbPutImage(drawable, gc, depth, x, y, w, h, leftPad, format, bits); 93 glamor_finish_access(drawable); 94} 95 96void 97glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y, 98 int w, int h, int leftPad, int format, char *bits) 99{ 100 if (glamor_put_image_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits)) 101 return; 102 glamor_put_image_bail(drawable, gc, depth, x, y, w, h, leftPad, format, bits); 103} 104 105static Bool 106glamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h, 107 unsigned int format, unsigned long plane_mask, char *d) 108{ 109 PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); 110 glamor_pixmap_private *pixmap_priv; 111 uint32_t byte_stride = PixmapBytePad(w, drawable->depth); 112 BoxRec box; 113 int off_x, off_y; 114 115 pixmap_priv = glamor_get_pixmap_private(pixmap); 116 if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) 117 goto bail; 118 119 if (format != ZPixmap) 120 goto bail; 121 122 glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y); 123 box.x1 = x; 124 box.x2 = x + w; 125 box.y1 = y; 126 box.y2 = y + h; 127 glamor_download_boxes(pixmap, &box, 1, 128 drawable->x + off_x, drawable->y + off_y, 129 -x, -y, 130 (uint8_t *) d, byte_stride); 131 132 if (!glamor_pm_is_solid(drawable->depth, plane_mask)) { 133 FbStip pm = fbReplicatePixel(plane_mask, drawable->bitsPerPixel); 134 FbStip *dst = (void *)d; 135 uint32_t dstStride = byte_stride / sizeof(FbStip); 136 137 for (int i = 0; i < dstStride * h; i++) 138 dst[i] &= pm; 139 } 140 141 return TRUE; 142bail: 143 return FALSE; 144} 145 146static void 147glamor_get_image_bail(DrawablePtr drawable, int x, int y, int w, int h, 148 unsigned int format, unsigned long plane_mask, char *d) 149{ 150 if (glamor_prepare_access_box(drawable, GLAMOR_ACCESS_RO, x, y, w, h)) 151 fbGetImage(drawable, x, y, w, h, format, plane_mask, d); 152 glamor_finish_access(drawable); 153} 154 155void 156glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h, 157 unsigned int format, unsigned long plane_mask, char *d) 158{ 159 if (glamor_get_image_gl(drawable, x, y, w, h, format, plane_mask, d)) 160 return; 161 glamor_get_image_bail(drawable, x, y, w, h, format, plane_mask, d); 162} 163