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
23
#include "glamor_priv.h"
24
#include "glamor_transfer.h"
26
/* XXX a kludge for now */
28
glamor_format_for_pixmap(PixmapPtr pixmap, GLenum *format, GLenum *type)
30
switch (pixmap->drawable.depth) {
34
*type = GL_UNSIGNED_INT_8_8_8_8_REV;
38
*type = GL_UNSIGNED_SHORT_5_6_5;
42
*type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
46
*type = GL_UNSIGNED_BYTE;
49
FatalError("Invalid pixmap depth %d\n", pixmap->drawable.depth);
55
* Write a region of bits into a pixmap
58
glamor_upload_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
59
int dx_src, int dy_src,
60
int dx_dst, int dy_dst,
61
uint8_t *bits, uint32_t byte_stride)
63
ScreenPtr screen = pixmap->drawable.pScreen;
64
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
65
glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
67
int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
71
glamor_format_for_pixmap(pixmap, &format, &type);
73
glamor_make_current(glamor_priv);
75
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
77
if (glamor_priv->has_unpack_subimage)
78
glPixelStorei(GL_UNPACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
80
glamor_pixmap_loop(priv, box_x, box_y) {
81
BoxPtr box = glamor_pixmap_box_at(priv, box_x, box_y);
82
glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y);
83
BoxPtr boxes = in_boxes;
86
glActiveTexture(GL_TEXTURE0);
87
glBindTexture(GL_TEXTURE_2D, fbo->tex);
91
/* compute drawable coordinates */
92
int x1 = MAX(boxes->x1 + dx_dst, box->x1);
93
int x2 = MIN(boxes->x2 + dx_dst, box->x2);
94
int y1 = MAX(boxes->y1 + dy_dst, box->y1);
95
int y2 = MIN(boxes->y2 + dy_dst, box->y2);
97
size_t ofs = (y1 - dy_dst + dy_src) * byte_stride;
98
ofs += (x1 - dx_dst + dx_src) * bytes_per_pixel;
102
if (x2 <= x1 || y2 <= y1)
105
if (glamor_priv->has_unpack_subimage ||
106
x2 - x1 == byte_stride / bytes_per_pixel) {
107
glTexSubImage2D(GL_TEXTURE_2D, 0,
108
x1 - box->x1, y1 - box->y1,
113
for (; y1 < y2; y1++, ofs += byte_stride)
114
glTexSubImage2D(GL_TEXTURE_2D, 0,
115
x1 - box->x1, y1 - box->y1,
123
if (glamor_priv->has_unpack_subimage)
124
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
128
* Upload a region of data
132
glamor_upload_region(PixmapPtr pixmap, RegionPtr region,
133
int region_x, int region_y,
134
uint8_t *bits, uint32_t byte_stride)
136
glamor_upload_boxes(pixmap, RegionRects(region), RegionNumRects(region),
137
-region_x, -region_y,
143
* Take the data in the pixmap and stuff it back into the FBO
146
glamor_upload_pixmap(PixmapPtr pixmap)
151
box.x2 = pixmap->drawable.width;
153
box.y2 = pixmap->drawable.height;
154
glamor_upload_boxes(pixmap, &box, 1, 0, 0, 0, 0,
155
pixmap->devPrivate.ptr, pixmap->devKind);
159
* Read stuff from the pixmap FBOs and write to memory
162
glamor_download_boxes(PixmapPtr pixmap, BoxPtr in_boxes, int in_nbox,
163
int dx_src, int dy_src,
164
int dx_dst, int dy_dst,
165
uint8_t *bits, uint32_t byte_stride)
167
ScreenPtr screen = pixmap->drawable.pScreen;
168
glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
169
glamor_pixmap_private *priv = glamor_get_pixmap_private(pixmap);
171
int bytes_per_pixel = pixmap->drawable.bitsPerPixel >> 3;
175
glamor_format_for_pixmap(pixmap, &format, &type);
177
glamor_make_current(glamor_priv);
179
glPixelStorei(GL_PACK_ALIGNMENT, 4);
180
if (glamor_priv->has_pack_subimage)
181
glPixelStorei(GL_PACK_ROW_LENGTH, byte_stride / bytes_per_pixel);
183
glamor_pixmap_loop(priv, box_x, box_y) {
184
BoxPtr box = glamor_pixmap_box_at(priv, box_x, box_y);
185
glamor_pixmap_fbo *fbo = glamor_pixmap_fbo_at(priv, box_x, box_y);
186
BoxPtr boxes = in_boxes;
189
glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
193
/* compute drawable coordinates */
194
int x1 = MAX(boxes->x1 + dx_src, box->x1);
195
int x2 = MIN(boxes->x2 + dx_src, box->x2);
196
int y1 = MAX(boxes->y1 + dy_src, box->y1);
197
int y2 = MIN(boxes->y2 + dy_src, box->y2);
198
size_t ofs = (y1 - dy_src + dy_dst) * byte_stride;
199
ofs += (x1 - dx_src + dx_dst) * bytes_per_pixel;
203
if (x2 <= x1 || y2 <= y1)
206
if (glamor_priv->has_pack_subimage ||
207
x2 - x1 == byte_stride / bytes_per_pixel) {
208
glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, y2 - y1, format, type, bits + ofs);
210
for (; y1 < y2; y1++, ofs += byte_stride)
211
glReadPixels(x1 - box->x1, y1 - box->y1, x2 - x1, 1, format, type, bits + ofs);
215
if (glamor_priv->has_pack_subimage)
216
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
220
* Read data from the pixmap FBO
223
glamor_download_rect(PixmapPtr pixmap, int x, int y, int w, int h, uint8_t *bits)
232
glamor_download_boxes(pixmap, &box, 1, 0, 0, -x, -y,
233
bits, PixmapBytePad(w, pixmap->drawable.depth));
237
* Pull the data from the FBO down to the pixmap
240
glamor_download_pixmap(PixmapPtr pixmap)
245
box.x2 = pixmap->drawable.width;
247
box.y2 = pixmap->drawable.height;
249
glamor_download_boxes(pixmap, &box, 1, 0, 0, 0, 0,
250
pixmap->devPrivate.ptr, pixmap->devKind);