2 * Copyright © 2016 Broadcom
3 * Copyright © 2009 Intel Corporation
4 * Copyright © 1998 Keith Packard
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
27 * @file glamor_picture.c
29 * Implements temporary uploads of GL_MEMORY Pixmaps to a texture that
30 * is swizzled appropriately for a given Render picture format.
33 * This is important because GTK likes to use SHM Pixmaps for Render
34 * blending operations, and we don't want a blend operation to fall
35 * back to software (readback is more expensive than the upload we do
36 * here, and you'd have to re-upload the fallback output anyway).
41 #include "glamor_priv.h"
44 static void byte_swap_swizzle(GLenum
*swizzle
)
49 swizzle
[0] = swizzle
[3];
53 swizzle
[1] = swizzle
[2];
58 * Returns the GL format and type for uploading our bits to a given PictFormat.
60 * We may need to tell the caller to translate the bits to another
61 * format, as in PICT_a1 (which GL doesn't support). We may also need
62 * to tell the GL to swizzle the texture on sampling, because GLES3
63 * doesn't support the GL_UNSIGNED_INT_8_8_8_8{,_REV} types, so we
64 * don't have enough channel reordering options at upload time without
68 glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen
,
69 PictFormatShort format
,
70 PictFormatShort
*temp_format
,
75 glamor_screen_private
*glamor_priv
= glamor_get_screen_private(pScreen
);
76 Bool is_little_endian
= IMAGE_BYTE_ORDER
== LSBFirst
;
78 *temp_format
= format
;
80 swizzle
[1] = GL_GREEN
;
82 swizzle
[3] = GL_ALPHA
;
86 *tex_format
= glamor_priv
->formats
[1].format
;
87 *tex_type
= GL_UNSIGNED_BYTE
;
88 *temp_format
= PICT_a8
;
93 if (!glamor_priv
->is_gles
) {
94 *tex_format
= GL_BGRA
;
95 *tex_type
= GL_UNSIGNED_INT_8_8_8_8
;
97 *tex_format
= GL_BGRA
;
98 *tex_type
= GL_UNSIGNED_BYTE
;
100 swizzle
[0] = GL_GREEN
;
101 swizzle
[1] = GL_BLUE
;
102 swizzle
[2] = GL_ALPHA
;
105 if (!is_little_endian
)
106 byte_swap_swizzle(swizzle
);
112 if (!glamor_priv
->is_gles
) {
113 *tex_format
= GL_BGRA
;
114 *tex_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
116 *tex_format
= GL_BGRA
;
117 *tex_type
= GL_UNSIGNED_BYTE
;
119 if (!is_little_endian
)
120 byte_swap_swizzle(swizzle
);
127 *tex_format
= GL_RGBA
;
128 if (!glamor_priv
->is_gles
) {
129 *tex_type
= GL_UNSIGNED_INT_8_8_8_8_REV
;
131 *tex_format
= GL_RGBA
;
132 *tex_type
= GL_UNSIGNED_BYTE
;
134 if (!is_little_endian
)
135 byte_swap_swizzle(swizzle
);
139 case PICT_x2r10g10b10
:
140 case PICT_a2r10g10b10
:
141 if (!glamor_priv
->is_gles
) {
142 *tex_format
= GL_BGRA
;
143 *tex_type
= GL_UNSIGNED_INT_2_10_10_10_REV
;
149 case PICT_x2b10g10r10
:
150 case PICT_a2b10g10r10
:
151 if (!glamor_priv
->is_gles
) {
152 *tex_format
= GL_RGBA
;
153 *tex_type
= GL_UNSIGNED_INT_2_10_10_10_REV
;
160 *tex_format
= GL_RGB
;
161 *tex_type
= GL_UNSIGNED_SHORT_5_6_5
;
164 *tex_format
= GL_RGB
;
165 if (!glamor_priv
->is_gles
) {
166 *tex_type
= GL_UNSIGNED_SHORT_5_6_5_REV
;
168 *tex_type
= GL_UNSIGNED_SHORT_5_6_5
;
169 swizzle
[0] = GL_BLUE
;
176 *tex_format
= GL_RGBA
;
177 if (!glamor_priv
->is_gles
) {
178 *tex_type
= GL_UNSIGNED_SHORT_1_5_5_5_REV
;
186 if (!glamor_priv
->is_gles
) {
187 *tex_format
= GL_BGRA
;
188 *tex_type
= GL_UNSIGNED_SHORT_1_5_5_5_REV
;
195 *tex_format
= glamor_priv
->formats
[8].format
;
196 *tex_type
= GL_UNSIGNED_BYTE
;
201 if (!glamor_priv
->is_gles
) {
202 *tex_format
= GL_BGRA
;
203 *tex_type
= GL_UNSIGNED_SHORT_4_4_4_4_REV
;
206 *tex_format
= GL_RGBA
;
207 *tex_type
= GL_UNSIGNED_SHORT_4_4_4_4
;
213 if (!glamor_priv
->is_gles
) {
214 *tex_format
= GL_RGBA
;
215 *tex_type
= GL_UNSIGNED_SHORT_4_4_4_4_REV
;
218 *tex_format
= GL_RGBA
;
219 *tex_type
= GL_UNSIGNED_SHORT_4_4_4_4
;
227 if (!PICT_FORMAT_A(format
))
234 * Takes a set of source bits with a given format and returns an
235 * in-memory pixman image of those bits in a destination format.
237 static pixman_image_t
*
238 glamor_get_converted_image(PictFormatShort dst_format
,
239 PictFormatShort src_format
,
244 pixman_image_t
*dst_image
;
245 pixman_image_t
*src_image
;
247 dst_image
= pixman_image_create_bits(dst_format
, w
, h
, NULL
, 0);
248 if (dst_image
== NULL
) {
252 src_image
= pixman_image_create_bits(src_format
, w
, h
, src_bits
, src_stride
);
254 if (src_image
== NULL
) {
255 pixman_image_unref(dst_image
);
259 pixman_image_composite(PictOpSrc
, src_image
, NULL
, dst_image
,
260 0, 0, 0, 0, 0, 0, w
, h
);
262 pixman_image_unref(src_image
);
267 * Uploads a picture based on a GLAMOR_MEMORY pixmap to a texture in a
271 glamor_upload_picture_to_texture(PicturePtr picture
)
273 PixmapPtr pixmap
= glamor_get_drawable_pixmap(picture
->pDrawable
);
274 ScreenPtr screen
= pixmap
->drawable
.pScreen
;
275 glamor_screen_private
*glamor_priv
= glamor_get_screen_private(screen
);
276 glamor_pixmap_private
*pixmap_priv
= glamor_get_pixmap_private(pixmap
);
277 PictFormatShort converted_format
;
278 void *bits
= pixmap
->devPrivate
.ptr
;
279 int stride
= pixmap
->devKind
;
285 pixman_image_t
*converted_image
= NULL
;
286 const struct glamor_format
*f
= glamor_format_for_pixmap(pixmap
);
288 assert(glamor_pixmap_is_memory(pixmap
));
289 assert(!pixmap_priv
->fbo
);
291 glamor_make_current(glamor_priv
);
293 /* No handling of large pixmap pictures here (would need to make
294 * an FBO array and split the uploads across it).
296 if (!glamor_check_fbo_size(glamor_priv
,
297 pixmap
->drawable
.width
,
298 pixmap
->drawable
.height
)) {
302 if (!glamor_get_tex_format_type_from_pictformat(screen
,
308 glamor_fallback("Unknown pixmap depth %d.\n", pixmap
->drawable
.depth
);
312 needs_swizzle
= (swizzle
[0] != GL_RED
||
313 swizzle
[1] != GL_GREEN
||
314 swizzle
[2] != GL_BLUE
||
315 swizzle
[3] != GL_ALPHA
);
317 if (!glamor_priv
->has_texture_swizzle
&& needs_swizzle
) {
318 glamor_fallback("Couldn't upload temporary picture due to missing "
319 "GL_ARB_texture_swizzle.\n");
323 if (converted_format
!= picture
->format
) {
324 converted_image
= glamor_get_converted_image(converted_format
,
327 pixmap
->drawable
.width
,
328 pixmap
->drawable
.height
);
329 if (!converted_image
)
332 bits
= pixman_image_get_data(converted_image
);
333 stride
= pixman_image_get_stride(converted_image
);
336 if (!glamor_priv
->is_gles
)
337 iformat
= f
->internalformat
;
341 if (!glamor_pixmap_ensure_fbo(pixmap
, GLAMOR_CREATE_FBO_NO_FBO
)) {
346 glPixelStorei(GL_UNPACK_ALIGNMENT
, 4);
348 glamor_priv
->suppress_gl_out_of_memory_logging
= true;
350 /* We can't use glamor_pixmap_loop() because GLAMOR_MEMORY pixmaps
351 * don't have initialized boxes.
353 glBindTexture(GL_TEXTURE_2D
, pixmap_priv
->fbo
->tex
);
354 glTexImage2D(GL_TEXTURE_2D
, 0, iformat
,
355 pixmap
->drawable
.width
, pixmap
->drawable
.height
, 0,
359 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_SWIZZLE_R
, swizzle
[0]);
360 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_SWIZZLE_G
, swizzle
[1]);
361 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_SWIZZLE_B
, swizzle
[2]);
362 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_SWIZZLE_A
, swizzle
[3]);
365 glamor_priv
->suppress_gl_out_of_memory_logging
= false;
366 if (glGetError() == GL_OUT_OF_MEMORY
) {
372 pixman_image_unref(converted_image
);