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
26 /* XXX a kludge for now */
27 void
glamor_format_for_pixmap(PixmapPtr pixmap,GLenum * format,GLenum * type)28 glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type)
29 {
30 switch (pixmap->drawable.depth) {
31 case 24:
32 case 32:
33 *format = GL_BGRA;
34 *type = GL_UNSIGNED_INT_8_8_8_8_REV;
35 break;
36 case 30:
37 *format = GL_BGRA;
38 *type = GL_UNSIGNED_INT_2_10_10_10_REV;
39 break;
40 case 16:
41 *format = GL_RGB;
42 *type = GL_UNSIGNED_SHORT_5_6_5;
43 break;
44 case 15:
45 *format = GL_BGRA;
46 *type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
47 break;
48 case 8:
49 *format = glamor_get_screen_private(pixmap->drawable.pScreen)->one_channel_format;
50 *type = GL_UNSIGNED_BYTE;
51 break;
52 default:
53 FatalError("Invalid pixmap depth %d\n", pixmap->drawable.depth);
54 break;
55 }
56 }
57
58 /*
59 * Write a region of bits into a pixmap
60 */
61 void
glamor_upload_boxes(PixmapPtr pixmap,BoxPtr in_boxes,int in_nbox,int dx_src,int dy_src,int dx_dst,int dy_dst,uint8_t * bits,uint32_t byte_stride)62 glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
63 int dx_src, int dy_src,
64 int dx_dst, int dy_dst,
65 uint8_t *bits, uint32_t byte_stride)
66 {
67 ScreenPtr screen = pixmap->drawable.pScreen;
68 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
69 glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
70 int box_index;
71 int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
72 GLenum type;
73 GLenum format;
74
75 glamor_format_for_pixmap(pixmap, &format, &type);
76
77 glamor_make_current(glamor_priv);
78
79 glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
80
81 if (glamor_priv->has_unpack_subimage)
82 glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
83
84 glamor_pixmap_loop(priv, box_index) {
85 BoxPtr box = glamor_pixmap_box_at(priv, box_index);
86 glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(priv, box_index);
87 BoxPtr boxes = in_boxes;
88 int nbox = in_nbox;
89
90 glamor_bind_texture(glamor_priv, GL_TEXTURE0, fbo, TRUE);
91
92 while (nbox--) {
93
94 /* compute drawable coordinates */
95 int x1 = MAX(boxes->x1 + dx_dst, box->x1);
96 int x2 = MIN(boxes->x2 + dx_dst, box->x2);
97 int y1 = MAX(boxes->y1 + dy_dst, box->y1);
98 int y2 = MIN(boxes->y2 + dy_dst, box->y2);
99
100 size_t ofs = (y1 - dy_dst + dy_src) * byte_stride;
101 ofs += (x1 - dx_dst + dx_src) * bytes_per_pixel;
102
103 boxes++;
104
105 if (x2 <= x1 || y2 <= y1)
106 continue;
107
108 if (glamor_priv->has_unpack_subimage ||
109 x2 - x1 == byte_stride / bytes_per_pixel) {
110 glTexSubImage2D(GL_TEXTURE_2D, 0,
111 x1 - box->x1, y1 - box->y1,
112 x2 - x1, y2 - y1,
113 format, type,
114 bits + ofs);
115 } else {
116 for (; y1 < y2; y1++, ofs += byte_stride)
117 glTexSubImage2D(GL_TEXTURE_2D, 0,
118 x1 - box->x1, y1 - box->y1,
119 x2 - x1, 1,
120 format, type,
121 bits + ofs);
122 }
123 }
124 }
125
126 if (glamor_priv->has_unpack_subimage)
127 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
128 }
129
130 /*
131 * Upload a region of data
132 */
133
134 void
glamor_upload_region(PixmapPtr pixmap,RegionPtr region,int region_x,int region_y,uint8_t * bits,uint32_t byte_stride)135 glamor_upload_region(PixmapPtr pixmap, RegionPtr region,
136 int region_x, int region_y,
137 uint8_t *bits, uint32_t byte_stride)
138 {
139 glamor_upload_boxes(pixmap, RegionRects(region), RegionNumRects(region),
140 -region_x, -region_y,
141 0, 0,
142 bits, byte_stride);
143 }
144
145 /*
146 * Take the data in the pixmap and stuff it back into the FBO
147 */
148 void
glamor_upload_pixmap(PixmapPtr pixmap)149 glamor_upload_pixmap(PixmapPtr pixmap)
150 {
151 BoxRec box;
152
153 box.x1 = 0;
154 box.x2 = pixmap->drawable.width;
155 box.y1 = 0;
156 box.y2 = pixmap->drawable.height;
157 glamor_upload_boxes(pixmap, &box, 1, 0, 0, 0, 0,
158 pixmap->devPrivate.ptr, pixmap->devKind);
159 }
160
161 /*
162 * Read stuff from the pixmap FBOs and write to memory
163 */
164 void
glamor_download_boxes(PixmapPtr pixmap,BoxPtr in_boxes,int in_nbox,int dx_src,int dy_src,int dx_dst,int dy_dst,uint8_t * bits,uint32_t byte_stride)165 glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
166 int dx_src, int dy_src,
167 int dx_dst, int dy_dst,
168 uint8_t *bits, uint32_t byte_stride)
169 {
170 ScreenPtr screen = pixmap->drawable.pScreen;
171 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
172 glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
173 int box_index;
174 int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
175 GLenum type;
176 GLenum format;
177
178 glamor_format_for_pixmap(pixmap, &format, &type);
179
180 glamor_make_current(glamor_priv);
181
182 glPixelStorei(GL_PACK_ALIGNMENT, 4);
183 if (glamor_priv->has_pack_subimage)
184 glPixelStorei(GL_PACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
185
186 glamor_pixmap_loop(priv, box_index) {
187 BoxPtr box = glamor_pixmap_box_at(priv, box_index);
188 glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(priv, box_index);
189 BoxPtr boxes = in_boxes;
190 int nbox = in_nbox;
191
192 /* This should not be called on GLAMOR_FBO_NO_FBO-allocated pixmaps. */
193 assert(fbo->fb);
194 glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
195
196 while (nbox--) {
197
198 /* compute drawable coordinates */
199 int x1 = MAX(boxes->x1 + dx_src, box->x1);
200 int x2 = MIN(boxes->x2 + dx_src, box->x2);
201 int y1 = MAX(boxes->y1 + dy_src, box->y1);
202 int y2 = MIN(boxes->y2 + dy_src, box->y2);
203 size_t ofs = (y1 - dy_src + dy_dst) * byte_stride;
204 ofs += (x1 - dx_src + dx_dst) * bytes_per_pixel;
205
206 boxes++;
207
208 if (x2 <= x1 || y2 <= y1)
209 continue;
210
211 if (glamor_priv->has_pack_subimage ||
212 x2 - x1 == byte_stride / bytes_per_pixel) {
213 glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, format, type, bits + ofs);
214 } else {
215 for (; y1 < y2; y1++, ofs += byte_stride)
216 glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, 1, format, type, bits + ofs);
217 }
218 }
219 }
220 if (glamor_priv->has_pack_subimage)
221 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
222 }
223
224 /*
225 * Read data from the pixmap FBO
226 */
227 void
glamor_download_rect(PixmapPtr pixmap,int x,int y,int w,int h,uint8_t * bits)228 glamor_download_rect(PixmapPtr pixmap, int x, int y, int w, int h, uint8_t *bits)
229 {
230 BoxRec box;
231
232 box.x1 = x;
233 box.x2 = x + w;
234 box.y1 = y;
235 box.y2 = y + h;
236
237 glamor_download_boxes(pixmap, &box, 1, 0, 0, -x, -y,
238 bits, PixmapBytePad(w, pixmap->drawable.depth));
239 }
240
241 /*
242 * Pull the data from the FBO down to the pixmap
243 */
244 void
glamor_download_pixmap(PixmapPtr pixmap)245 glamor_download_pixmap(PixmapPtr pixmap)
246 {
247 BoxRec box;
248
249 box.x1 = 0;
250 box.x2 = pixmap->drawable.width;
251 box.y1 = 0;
252 box.y2 = pixmap->drawable.height;
253
254 glamor_download_boxes(pixmap, &box, 1, 0, 0, 0, 0,
255 pixmap->devPrivate.ptr, pixmap->devKind);
256 }
257