135c4bbdfSmrg/* 21b5d61b8Smrg * Copyright © 2016 Broadcom 335c4bbdfSmrg * Copyright © 2009 Intel Corporation 435c4bbdfSmrg * Copyright © 1998 Keith Packard 535c4bbdfSmrg * 635c4bbdfSmrg * Permission is hereby granted, free of charge, to any person obtaining a 735c4bbdfSmrg * copy of this software and associated documentation files (the "Software"), 835c4bbdfSmrg * to deal in the Software without restriction, including without limitation 935c4bbdfSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1035c4bbdfSmrg * and/or sell copies of the Software, and to permit persons to whom the 1135c4bbdfSmrg * Software is furnished to do so, subject to the following conditions: 1235c4bbdfSmrg * 1335c4bbdfSmrg * The above copyright notice and this permission notice (including the next 1435c4bbdfSmrg * paragraph) shall be included in all copies or substantial portions of the 1535c4bbdfSmrg * Software. 1635c4bbdfSmrg * 1735c4bbdfSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1835c4bbdfSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1935c4bbdfSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2035c4bbdfSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 2135c4bbdfSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2235c4bbdfSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 2335c4bbdfSmrg * IN THE SOFTWARE. 241b5d61b8Smrg */ 251b5d61b8Smrg 261b5d61b8Smrg/** 271b5d61b8Smrg * @file glamor_picture.c 2835c4bbdfSmrg * 291b5d61b8Smrg * Implements temporary uploads of GL_MEMORY Pixmaps to a texture that 301b5d61b8Smrg * is swizzled appropriately for a given Render picture format. 311b5d61b8Smrg * laid * 3235c4bbdfSmrg * 331b5d61b8Smrg * This is important because GTK likes to use SHM Pixmaps for Render 341b5d61b8Smrg * blending operations, and we don't want a blend operation to fall 351b5d61b8Smrg * back to software (readback is more expensive than the upload we do 361b5d61b8Smrg * here, and you'd have to re-upload the fallback output anyway). 3735c4bbdfSmrg */ 3835c4bbdfSmrg 3935c4bbdfSmrg#include <stdlib.h> 4035c4bbdfSmrg 4135c4bbdfSmrg#include "glamor_priv.h" 4235c4bbdfSmrg#include "mipict.h" 4335c4bbdfSmrg 441b5d61b8Smrgstatic void byte_swap_swizzle(GLenum *swizzle) 4535c4bbdfSmrg{ 461b5d61b8Smrg GLenum temp; 4735c4bbdfSmrg 481b5d61b8Smrg temp = swizzle[0]; 491b5d61b8Smrg swizzle[0] = swizzle[3]; 501b5d61b8Smrg swizzle[3] = temp; 5135c4bbdfSmrg 521b5d61b8Smrg temp = swizzle[1]; 531b5d61b8Smrg swizzle[1] = swizzle[2]; 541b5d61b8Smrg swizzle[2] = temp; 5535c4bbdfSmrg} 5635c4bbdfSmrg 571b5d61b8Smrg/** 581b5d61b8Smrg * Returns the GL format and type for uploading our bits to a given PictFormat. 591b5d61b8Smrg * 601b5d61b8Smrg * We may need to tell the caller to translate the bits to another 611b5d61b8Smrg * format, as in PICT_a1 (which GL doesn't support). We may also need 621b5d61b8Smrg * to tell the GL to swizzle the texture on sampling, because GLES3 631b5d61b8Smrg * doesn't support the GL_UNSIGNED_INT_8_8_8_8{,_REV} types, so we 641b5d61b8Smrg * don't have enough channel reordering options at upload time without 651b5d61b8Smrg * it. 661b5d61b8Smrg */ 671b5d61b8Smrgstatic Bool 681b5d61b8Smrgglamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen, 691b5d61b8Smrg PictFormatShort format, 701b5d61b8Smrg PictFormatShort *temp_format, 711b5d61b8Smrg GLenum *tex_format, 721b5d61b8Smrg GLenum *tex_type, 731b5d61b8Smrg GLenum *swizzle) 7435c4bbdfSmrg{ 7535c4bbdfSmrg glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen); 761b5d61b8Smrg Bool is_little_endian = IMAGE_BYTE_ORDER == LSBFirst; 7735c4bbdfSmrg 781b5d61b8Smrg *temp_format = format; 791b5d61b8Smrg swizzle[0] = GL_RED; 801b5d61b8Smrg swizzle[1] = GL_GREEN; 811b5d61b8Smrg swizzle[2] = GL_BLUE; 821b5d61b8Smrg swizzle[3] = GL_ALPHA; 8335c4bbdfSmrg 8435c4bbdfSmrg switch (format) { 851b5d61b8Smrg case PICT_a1: 86ed6184dfSmrg *tex_format = glamor_priv->formats[1].format; 871b5d61b8Smrg *tex_type = GL_UNSIGNED_BYTE; 881b5d61b8Smrg *temp_format = PICT_a8; 891b5d61b8Smrg break; 901b5d61b8Smrg 9135c4bbdfSmrg case PICT_b8g8r8x8: 9235c4bbdfSmrg case PICT_b8g8r8a8: 93ed6184dfSmrg if (!glamor_priv->is_gles) { 941b5d61b8Smrg *tex_format = GL_BGRA; 951b5d61b8Smrg *tex_type = GL_UNSIGNED_INT_8_8_8_8; 961b5d61b8Smrg } else { 9758cf2af7Smrg *tex_format = GL_BGRA; 981b5d61b8Smrg *tex_type = GL_UNSIGNED_BYTE; 991b5d61b8Smrg 1001b5d61b8Smrg swizzle[0] = GL_GREEN; 1011b5d61b8Smrg swizzle[1] = GL_BLUE; 1021b5d61b8Smrg swizzle[2] = GL_ALPHA; 1031b5d61b8Smrg swizzle[3] = GL_RED; 1041b5d61b8Smrg 1051b5d61b8Smrg if (!is_little_endian) 1061b5d61b8Smrg byte_swap_swizzle(swizzle); 1071b5d61b8Smrg } 10835c4bbdfSmrg break; 10935c4bbdfSmrg 11035c4bbdfSmrg case PICT_x8r8g8b8: 11135c4bbdfSmrg case PICT_a8r8g8b8: 112ed6184dfSmrg if (!glamor_priv->is_gles) { 1131b5d61b8Smrg *tex_format = GL_BGRA; 1141b5d61b8Smrg *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; 1151b5d61b8Smrg } else { 11658cf2af7Smrg *tex_format = GL_BGRA; 1171b5d61b8Smrg *tex_type = GL_UNSIGNED_BYTE; 1181b5d61b8Smrg 1191b5d61b8Smrg if (!is_little_endian) 1201b5d61b8Smrg byte_swap_swizzle(swizzle); 1211b5d61b8Smrg break; 1221b5d61b8Smrg } 12335c4bbdfSmrg break; 12435c4bbdfSmrg 12535c4bbdfSmrg case PICT_x8b8g8r8: 12635c4bbdfSmrg case PICT_a8b8g8r8: 12735c4bbdfSmrg *tex_format = GL_RGBA; 128ed6184dfSmrg if (!glamor_priv->is_gles) { 1291b5d61b8Smrg *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV; 1301b5d61b8Smrg } else { 1311b5d61b8Smrg *tex_format = GL_RGBA; 1321b5d61b8Smrg *tex_type = GL_UNSIGNED_BYTE; 1331b5d61b8Smrg 1341b5d61b8Smrg if (!is_little_endian) 1351b5d61b8Smrg byte_swap_swizzle(swizzle); 1361b5d61b8Smrg } 13735c4bbdfSmrg break; 13835c4bbdfSmrg 13935c4bbdfSmrg case PICT_x2r10g10b10: 14035c4bbdfSmrg case PICT_a2r10g10b10: 141ed6184dfSmrg if (!glamor_priv->is_gles) { 1421b5d61b8Smrg *tex_format = GL_BGRA; 1431b5d61b8Smrg *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; 1441b5d61b8Smrg } else { 1451b5d61b8Smrg return FALSE; 14635c4bbdfSmrg } 14735c4bbdfSmrg break; 14835c4bbdfSmrg 14935c4bbdfSmrg case PICT_x2b10g10r10: 15035c4bbdfSmrg case PICT_a2b10g10r10: 151ed6184dfSmrg if (!glamor_priv->is_gles) { 1521b5d61b8Smrg *tex_format = GL_RGBA; 1531b5d61b8Smrg *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV; 1541b5d61b8Smrg } else { 1551b5d61b8Smrg return FALSE; 15635c4bbdfSmrg } 15735c4bbdfSmrg break; 15835c4bbdfSmrg 15935c4bbdfSmrg case PICT_r5g6b5: 16035c4bbdfSmrg *tex_format = GL_RGB; 16135c4bbdfSmrg *tex_type = GL_UNSIGNED_SHORT_5_6_5; 16235c4bbdfSmrg break; 16335c4bbdfSmrg case PICT_b5g6r5: 16435c4bbdfSmrg *tex_format = GL_RGB; 165ed6184dfSmrg if (!glamor_priv->is_gles) { 1661b5d61b8Smrg *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV; 1671b5d61b8Smrg } else { 1681b5d61b8Smrg *tex_type = GL_UNSIGNED_SHORT_5_6_5; 1691b5d61b8Smrg swizzle[0] = GL_BLUE; 1701b5d61b8Smrg swizzle[2] = GL_RED; 1711b5d61b8Smrg } 17235c4bbdfSmrg break; 17335c4bbdfSmrg 17435c4bbdfSmrg case PICT_x1b5g5r5: 17535c4bbdfSmrg case PICT_a1b5g5r5: 17635c4bbdfSmrg *tex_format = GL_RGBA; 177ed6184dfSmrg if (!glamor_priv->is_gles) { 1781b5d61b8Smrg *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; 1791b5d61b8Smrg } else { 1801b5d61b8Smrg return FALSE; 18135c4bbdfSmrg } 18235c4bbdfSmrg break; 18335c4bbdfSmrg 18435c4bbdfSmrg case PICT_x1r5g5b5: 18535c4bbdfSmrg case PICT_a1r5g5b5: 186ed6184dfSmrg if (!glamor_priv->is_gles) { 1871b5d61b8Smrg *tex_format = GL_BGRA; 1881b5d61b8Smrg *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; 1891b5d61b8Smrg } else { 1901b5d61b8Smrg return FALSE; 19135c4bbdfSmrg } 19235c4bbdfSmrg break; 19335c4bbdfSmrg 19435c4bbdfSmrg case PICT_a8: 195ed6184dfSmrg *tex_format = glamor_priv->formats[8].format; 19635c4bbdfSmrg *tex_type = GL_UNSIGNED_BYTE; 19735c4bbdfSmrg break; 19835c4bbdfSmrg 19935c4bbdfSmrg case PICT_x4r4g4b4: 20035c4bbdfSmrg case PICT_a4r4g4b4: 201ed6184dfSmrg if (!glamor_priv->is_gles) { 2021b5d61b8Smrg *tex_format = GL_BGRA; 2031b5d61b8Smrg *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; 2041b5d61b8Smrg } else { 2051b5d61b8Smrg /* XXX */ 2061b5d61b8Smrg *tex_format = GL_RGBA; 2071b5d61b8Smrg *tex_type = GL_UNSIGNED_SHORT_4_4_4_4; 2081b5d61b8Smrg } 20935c4bbdfSmrg break; 21035c4bbdfSmrg 21135c4bbdfSmrg case PICT_x4b4g4r4: 21235c4bbdfSmrg case PICT_a4b4g4r4: 213ed6184dfSmrg if (!glamor_priv->is_gles) { 2141b5d61b8Smrg *tex_format = GL_RGBA; 2151b5d61b8Smrg *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; 2161b5d61b8Smrg } else { 2171b5d61b8Smrg /* XXX */ 2181b5d61b8Smrg *tex_format = GL_RGBA; 2191b5d61b8Smrg *tex_type = GL_UNSIGNED_SHORT_4_4_4_4; 2201b5d61b8Smrg } 22135c4bbdfSmrg break; 22235c4bbdfSmrg 22335c4bbdfSmrg default: 2241b5d61b8Smrg return FALSE; 22535c4bbdfSmrg } 22635c4bbdfSmrg 2271b5d61b8Smrg if (!PICT_FORMAT_A(format)) 2281b5d61b8Smrg swizzle[3] = GL_ONE; 22935c4bbdfSmrg 2301b5d61b8Smrg return TRUE; 23135c4bbdfSmrg} 23235c4bbdfSmrg 2331b5d61b8Smrg/** 2341b5d61b8Smrg * Takes a set of source bits with a given format and returns an 2351b5d61b8Smrg * in-memory pixman image of those bits in a destination format. 2361b5d61b8Smrg */ 2371b5d61b8Smrgstatic pixman_image_t * 2381b5d61b8Smrgglamor_get_converted_image(PictFormatShort dst_format, 2391b5d61b8Smrg PictFormatShort src_format, 2401b5d61b8Smrg void *src_bits, 2411b5d61b8Smrg int src_stride, 2421b5d61b8Smrg int w, int h) 24335c4bbdfSmrg{ 24435c4bbdfSmrg pixman_image_t *dst_image; 24535c4bbdfSmrg pixman_image_t *src_image; 24635c4bbdfSmrg 2471b5d61b8Smrg dst_image = pixman_image_create_bits(dst_format, w, h, NULL, 0); 24835c4bbdfSmrg if (dst_image == NULL) { 24935c4bbdfSmrg return NULL; 25035c4bbdfSmrg } 25135c4bbdfSmrg 2521b5d61b8Smrg src_image = pixman_image_create_bits(src_format, w, h, src_bits, src_stride); 25335c4bbdfSmrg 25435c4bbdfSmrg if (src_image == NULL) { 25535c4bbdfSmrg pixman_image_unref(dst_image); 25635c4bbdfSmrg return NULL; 25735c4bbdfSmrg } 25835c4bbdfSmrg 25935c4bbdfSmrg pixman_image_composite(PictOpSrc, src_image, NULL, dst_image, 26035c4bbdfSmrg 0, 0, 0, 0, 0, 0, w, h); 26135c4bbdfSmrg 26235c4bbdfSmrg pixman_image_unref(src_image); 2631b5d61b8Smrg return dst_image; 26435c4bbdfSmrg} 26535c4bbdfSmrg 26635c4bbdfSmrg/** 2671b5d61b8Smrg * Uploads a picture based on a GLAMOR_MEMORY pixmap to a texture in a 2681b5d61b8Smrg * temporary FBO. 2691b5d61b8Smrg */ 2701b5d61b8SmrgBool 2711b5d61b8Smrgglamor_upload_picture_to_texture(PicturePtr picture) 27235c4bbdfSmrg{ 2731b5d61b8Smrg PixmapPtr pixmap = glamor_get_drawable_pixmap(picture->pDrawable); 27435c4bbdfSmrg ScreenPtr screen = pixmap->drawable.pScreen; 2751b5d61b8Smrg glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 27635c4bbdfSmrg glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); 2771b5d61b8Smrg PictFormatShort converted_format; 2781b5d61b8Smrg void *bits = pixmap->devPrivate.ptr; 2791b5d61b8Smrg int stride = pixmap->devKind; 2801b5d61b8Smrg GLenum format, type; 2811b5d61b8Smrg GLenum swizzle[4]; 2821b5d61b8Smrg GLenum iformat; 2831b5d61b8Smrg Bool ret = TRUE; 2841b5d61b8Smrg Bool needs_swizzle; 2851b5d61b8Smrg pixman_image_t *converted_image = NULL; 286ed6184dfSmrg const struct glamor_format *f = glamor_format_for_pixmap(pixmap); 28735c4bbdfSmrg 2881b5d61b8Smrg assert(glamor_pixmap_is_memory(pixmap)); 2891b5d61b8Smrg assert(!pixmap_priv->fbo); 29035c4bbdfSmrg 2911b5d61b8Smrg glamor_make_current(glamor_priv); 29235c4bbdfSmrg 2931b5d61b8Smrg /* No handling of large pixmap pictures here (would need to make 2941b5d61b8Smrg * an FBO array and split the uploads across it). 2951b5d61b8Smrg */ 2961b5d61b8Smrg if (!glamor_check_fbo_size(glamor_priv, 2971b5d61b8Smrg pixmap->drawable.width, 2981b5d61b8Smrg pixmap->drawable.height)) { 2991b5d61b8Smrg return FALSE; 30035c4bbdfSmrg } 30135c4bbdfSmrg 3021b5d61b8Smrg if (!glamor_get_tex_format_type_from_pictformat(screen, 3031b5d61b8Smrg picture->format, 3041b5d61b8Smrg &converted_format, 3051b5d61b8Smrg &format, 3061b5d61b8Smrg &type, 3071b5d61b8Smrg swizzle)) { 3081b5d61b8Smrg glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth); 3091b5d61b8Smrg return FALSE; 31035c4bbdfSmrg } 31135c4bbdfSmrg 3121b5d61b8Smrg needs_swizzle = (swizzle[0] != GL_RED || 3131b5d61b8Smrg swizzle[1] != GL_GREEN || 3141b5d61b8Smrg swizzle[2] != GL_BLUE || 3151b5d61b8Smrg swizzle[3] != GL_ALPHA); 31635c4bbdfSmrg 3171b5d61b8Smrg if (!glamor_priv->has_texture_swizzle && needs_swizzle) { 3181b5d61b8Smrg glamor_fallback("Couldn't upload temporary picture due to missing " 3191b5d61b8Smrg "GL_ARB_texture_swizzle.\n"); 3201b5d61b8Smrg return FALSE; 32135c4bbdfSmrg } 32235c4bbdfSmrg 3231b5d61b8Smrg if (converted_format != picture->format) { 3241b5d61b8Smrg converted_image = glamor_get_converted_image(converted_format, 3251b5d61b8Smrg picture->format, 3261b5d61b8Smrg bits, stride, 3271b5d61b8Smrg pixmap->drawable.width, 3281b5d61b8Smrg pixmap->drawable.height); 3291b5d61b8Smrg if (!converted_image) 3301b5d61b8Smrg return FALSE; 33135c4bbdfSmrg 3321b5d61b8Smrg bits = pixman_image_get_data(converted_image); 3331b5d61b8Smrg stride = pixman_image_get_stride(converted_image); 33435c4bbdfSmrg } 33535c4bbdfSmrg 336ed6184dfSmrg if (!glamor_priv->is_gles) 337ed6184dfSmrg iformat = f->internalformat; 33835c4bbdfSmrg else 33935c4bbdfSmrg iformat = format; 34035c4bbdfSmrg 341ed6184dfSmrg if (!glamor_pixmap_ensure_fbo(pixmap, GLAMOR_CREATE_FBO_NO_FBO)) { 3425a7dfde8Smrg ret = FALSE; 3431b5d61b8Smrg goto fail; 3445a7dfde8Smrg } 34535c4bbdfSmrg 3461b5d61b8Smrg glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 34735c4bbdfSmrg 3481b5d61b8Smrg glamor_priv->suppress_gl_out_of_memory_logging = true; 34935c4bbdfSmrg 3501b5d61b8Smrg /* We can't use glamor_pixmap_loop() because GLAMOR_MEMORY pixmaps 3511b5d61b8Smrg * don't have initialized boxes. 3521b5d61b8Smrg */ 3531b5d61b8Smrg glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex); 3541b5d61b8Smrg glTexImage2D(GL_TEXTURE_2D, 0, iformat, 3551b5d61b8Smrg pixmap->drawable.width, pixmap->drawable.height, 0, 3561b5d61b8Smrg format, type, bits); 3571b5d61b8Smrg 3581b5d61b8Smrg if (needs_swizzle) { 3591b5d61b8Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, swizzle[0]); 3601b5d61b8Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, swizzle[1]); 3611b5d61b8Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, swizzle[2]); 3621b5d61b8Smrg glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, swizzle[3]); 36335c4bbdfSmrg } 36435c4bbdfSmrg 3651b5d61b8Smrg glamor_priv->suppress_gl_out_of_memory_logging = false; 3661b5d61b8Smrg if (glGetError() == GL_OUT_OF_MEMORY) { 3671b5d61b8Smrg ret = FALSE; 36835c4bbdfSmrg } 36935c4bbdfSmrg 3701b5d61b8Smrgfail: 3711b5d61b8Smrg if (converted_image) 3721b5d61b8Smrg pixman_image_unref(converted_image); 37335c4bbdfSmrg 3741b5d61b8Smrg return ret; 37535c4bbdfSmrg} 376