xref: /OK3568_Linux_fs/external/xserver/glamor/glamor_image.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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 
31 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)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)
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(&region, &box, 1);
68     RegionIntersect(&region, &region, 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(&region, off_x, off_y);
75     }
76 
77     glamor_make_current(glamor_priv);
78 
79     glamor_upload_region(pixmap, &region, x, y, (uint8_t *) bits, byte_stride);
80 
81     RegionUninit(&region);
82 
83     glamor_pixmap_invalid(pixmap);
84 
85     return TRUE;
86 bail:
87     return FALSE;
88 }
89 
90 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)91 glamor_put_image_bail(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
92                       int w, int h, int leftPad, int format, char *bits)
93 {
94     if (glamor_prepare_access_box(drawable, GLAMOR_ACCESS_RW, x, y, w, h))
95         fbPutImage(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
96     glamor_finish_access(drawable);
97 }
98 
99 void
glamor_put_image(DrawablePtr drawable,GCPtr gc,int depth,int x,int y,int w,int h,int leftPad,int format,char * bits)100 glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
101                  int w, int h, int leftPad, int format, char *bits)
102 {
103     if (GLAMOR_PREFER_GL() &&
104         glamor_put_image_gl(drawable, gc, depth, x, y, w, h, leftPad, format, bits))
105         return;
106     glamor_put_image_bail(drawable, gc, depth, x, y, w, h, leftPad, format, bits);
107 }
108 
109 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)110 glamor_get_image_gl(DrawablePtr drawable, int x, int y, int w, int h,
111                     unsigned int format, unsigned long plane_mask, char *d)
112 {
113     PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
114     glamor_pixmap_private *pixmap_priv;
115     uint32_t    byte_stride = PixmapBytePad(w, drawable->depth);
116     BoxRec      box;
117     int         off_x, off_y;
118 
119     pixmap_priv = glamor_get_pixmap_private(pixmap);
120     if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
121         goto bail;
122 
123     if (format != ZPixmap)
124         goto bail;
125 
126     glamor_get_drawable_deltas(drawable, pixmap, &off_x, &off_y);
127     box.x1 = x;
128     box.x2 = x + w;
129     box.y1 = y;
130     box.y2 = y + h;
131     glamor_download_boxes(pixmap, &box, 1,
132                           drawable->x + off_x, drawable->y + off_y,
133                           -x, -y,
134                           (uint8_t *) d, byte_stride);
135 
136     if (!glamor_pm_is_solid(drawable->depth, plane_mask)) {
137         FbStip pm = fbReplicatePixel(plane_mask, drawable->bitsPerPixel);
138         FbStip *dst = (void *)d;
139         uint32_t dstStride = byte_stride / sizeof(FbStip);
140 
141         for (int i = 0; i < dstStride * h; i++)
142             dst[i] &= pm;
143     }
144 
145     return TRUE;
146 bail:
147     return FALSE;
148 }
149 
150 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)151 glamor_get_image_bail(DrawablePtr drawable, int x, int y, int w, int h,
152                       unsigned int format, unsigned long plane_mask, char *d)
153 {
154     if (glamor_prepare_access_box(drawable, GLAMOR_ACCESS_RO, x, y, w, h))
155         fbGetImage(drawable, x, y, w, h, format, plane_mask, d);
156     glamor_finish_access(drawable);
157 }
158 
159 void
glamor_get_image(DrawablePtr drawable,int x,int y,int w,int h,unsigned int format,unsigned long plane_mask,char * d)160 glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h,
161                  unsigned int format, unsigned long plane_mask, char *d)
162 {
163     if (GLAMOR_PREFER_GL() &&
164         glamor_get_image_gl(drawable, x, y, w, h, format, plane_mask, d))
165         return;
166     glamor_get_image_bail(drawable, x, y, w, h, format, plane_mask, d);
167 }
168