No longer leak FDs on VT switch.
[xserver.git] / glamor / glamor_image.c
blob28bdc159f0575119f3b6eb89d20603925ba179e4
1 /*
2 * Copyright © 2014 Keith Packard
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.
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.
23 #include "glamor_priv.h"
24 #include "glamor_transfer.h"
25 #include "glamor_transform.h"
28 * PutImage. Only does ZPixmap right now as other formats are quite a bit harder
31 static Bool
32 glamor_put_image_gl(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
33 int w, int h, int leftPad, int format, char *bits)
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;
44 pixmap_priv = glamor_get_pixmap_private(pixmap);
46 if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
47 return FALSE;
49 if (gc->alu != GXcopy)
50 goto bail;
52 if (!glamor_pm_is_solid(gc->depth, gc->planemask))
53 goto bail;
55 if (format == XYPixmap && drawable->depth == 1 && leftPad == 0)
56 format = ZPixmap;
58 if (format != ZPixmap)
59 goto bail;
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(&region, &box, 1);
68 RegionIntersect(&region, &region, gc->pCompositeClip);
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(&region, off_x, off_y);
77 glamor_make_current(glamor_priv);
79 glamor_upload_region(drawable, &region, x, y, (uint8_t *) bits, byte_stride);
81 RegionUninit(&region);
82 return TRUE;
83 bail:
84 return FALSE;
87 static void
88 glamor_put_image_bail(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
89 int w, int h, int leftPad, int format, char *bits)
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);
96 void
97 glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
98 int w, int h, int leftPad, int format, char *bits)
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);
105 static Bool
106 glamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h,
107 unsigned int format, unsigned long plane_mask, char *d)
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;
115 pixmap_priv = glamor_get_pixmap_private(pixmap);
116 if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
117 goto bail;
119 if (format != ZPixmap)
120 goto bail;
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(drawable, &box, 1,
128 drawable->x + off_x, drawable->y + off_y,
129 -x, -y,
130 (uint8_t *) d, byte_stride);
132 if (!glamor_pm_is_solid(glamor_drawable_effective_depth(drawable), plane_mask)) {
133 FbStip pm = fbReplicatePixel(plane_mask, drawable->bitsPerPixel);
134 FbStip *dst = (void *)d;
135 uint32_t dstStride = byte_stride / sizeof(FbStip);
137 for (int i = 0; i < dstStride * h; i++)
138 dst[i] &= pm;
141 return TRUE;
142 bail:
143 return FALSE;
146 static void
147 glamor_get_image_bail(DrawablePtr drawable, int x, int y, int w, int h,
148 unsigned int format, unsigned long plane_mask, char *d)
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);
155 void
156 glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h,
157 unsigned int format, unsigned long plane_mask, char *d)
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);