xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

glamor_picture.c (11742B)


      1 /*
      2  * Copyright © 2016 Broadcom
      3  * Copyright © 2009 Intel Corporation
      4  * Copyright © 1998 Keith Packard
      5  *
      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:
     12  *
     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
     15  * Software.
     16  *
     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
     23  * IN THE SOFTWARE.
     24  */
     25 
     26 /**
     27  * @file glamor_picture.c
     28  *
     29  * Implements temporary uploads of GL_MEMORY Pixmaps to a texture that
     30  * is swizzled appropriately for a given Render picture format.
     31  * laid *
     32  *
     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).
     37  */
     38 
     39 #include <stdlib.h>
     40 
     41 #include "glamor_priv.h"
     42 #include "mipict.h"
     43 
     44 static void byte_swap_swizzle(GLenum *swizzle)
     45 {
     46     GLenum temp;
     47 
     48     temp = swizzle[0];
     49     swizzle[0] = swizzle[3];
     50     swizzle[3] = temp;
     51 
     52     temp = swizzle[1];
     53     swizzle[1] = swizzle[2];
     54     swizzle[2] = temp;
     55 }
     56 
     57 /**
     58  * Returns the GL format and type for uploading our bits to a given PictFormat.
     59  *
     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
     65  * it.
     66  */
     67 static Bool
     68 glamor_get_tex_format_type_from_pictformat(ScreenPtr pScreen,
     69                                            PictFormatShort format,
     70                                            PictFormatShort *temp_format,
     71                                            GLenum *tex_format,
     72                                            GLenum *tex_type,
     73                                            GLenum *swizzle)
     74 {
     75     glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen);
     76     Bool is_little_endian = IMAGE_BYTE_ORDER == LSBFirst;
     77 
     78     *temp_format = format;
     79     swizzle[0] = GL_RED;
     80     swizzle[1] = GL_GREEN;
     81     swizzle[2] = GL_BLUE;
     82     swizzle[3] = GL_ALPHA;
     83 
     84     switch (format) {
     85     case PICT_a1:
     86         *tex_format = glamor_priv->formats[1].format;
     87         *tex_type = GL_UNSIGNED_BYTE;
     88         *temp_format = PICT_a8;
     89         break;
     90 
     91     case PICT_b8g8r8x8:
     92     case PICT_b8g8r8a8:
     93         if (!glamor_priv->is_gles) {
     94             *tex_format = GL_BGRA;
     95             *tex_type = GL_UNSIGNED_INT_8_8_8_8;
     96         } else {
     97             *tex_format = GL_RGBA;
     98             *tex_type = GL_UNSIGNED_BYTE;
     99 
    100             swizzle[0] = GL_GREEN;
    101             swizzle[1] = GL_BLUE;
    102             swizzle[2] = GL_ALPHA;
    103             swizzle[3] = GL_RED;
    104 
    105             if (!is_little_endian)
    106                 byte_swap_swizzle(swizzle);
    107         }
    108         break;
    109 
    110     case PICT_x8r8g8b8:
    111     case PICT_a8r8g8b8:
    112         if (!glamor_priv->is_gles) {
    113             *tex_format = GL_BGRA;
    114             *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
    115         } else {
    116             *tex_format = GL_RGBA;
    117             *tex_type = GL_UNSIGNED_BYTE;
    118 
    119             swizzle[0] = GL_BLUE;
    120             swizzle[2] = GL_RED;
    121 
    122             if (!is_little_endian)
    123                 byte_swap_swizzle(swizzle);
    124             break;
    125         }
    126         break;
    127 
    128     case PICT_x8b8g8r8:
    129     case PICT_a8b8g8r8:
    130         *tex_format = GL_RGBA;
    131         if (!glamor_priv->is_gles) {
    132             *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
    133         } else {
    134             *tex_format = GL_RGBA;
    135             *tex_type = GL_UNSIGNED_BYTE;
    136 
    137             if (!is_little_endian)
    138                 byte_swap_swizzle(swizzle);
    139         }
    140         break;
    141 
    142     case PICT_x2r10g10b10:
    143     case PICT_a2r10g10b10:
    144         if (!glamor_priv->is_gles) {
    145             *tex_format = GL_BGRA;
    146             *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
    147         } else {
    148             return FALSE;
    149         }
    150         break;
    151 
    152     case PICT_x2b10g10r10:
    153     case PICT_a2b10g10r10:
    154         if (!glamor_priv->is_gles) {
    155             *tex_format = GL_RGBA;
    156             *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
    157         } else {
    158             return FALSE;
    159         }
    160         break;
    161 
    162     case PICT_r5g6b5:
    163         *tex_format = GL_RGB;
    164         *tex_type = GL_UNSIGNED_SHORT_5_6_5;
    165         break;
    166     case PICT_b5g6r5:
    167         *tex_format = GL_RGB;
    168         if (!glamor_priv->is_gles) {
    169             *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV;
    170         } else {
    171             *tex_type = GL_UNSIGNED_SHORT_5_6_5;
    172             swizzle[0] = GL_BLUE;
    173             swizzle[2] = GL_RED;
    174         }
    175         break;
    176 
    177     case PICT_x1b5g5r5:
    178     case PICT_a1b5g5r5:
    179         *tex_format = GL_RGBA;
    180         if (!glamor_priv->is_gles) {
    181             *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
    182         } else {
    183             return FALSE;
    184         }
    185         break;
    186 
    187     case PICT_x1r5g5b5:
    188     case PICT_a1r5g5b5:
    189         if (!glamor_priv->is_gles) {
    190             *tex_format = GL_BGRA;
    191             *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
    192         } else {
    193             return FALSE;
    194         }
    195         break;
    196 
    197     case PICT_a8:
    198         *tex_format = glamor_priv->formats[8].format;
    199         *tex_type = GL_UNSIGNED_BYTE;
    200         break;
    201 
    202     case PICT_x4r4g4b4:
    203     case PICT_a4r4g4b4:
    204         if (!glamor_priv->is_gles) {
    205             *tex_format = GL_BGRA;
    206             *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
    207         } else {
    208             /* XXX */
    209             *tex_format = GL_RGBA;
    210             *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
    211         }
    212         break;
    213 
    214     case PICT_x4b4g4r4:
    215     case PICT_a4b4g4r4:
    216         if (!glamor_priv->is_gles) {
    217             *tex_format = GL_RGBA;
    218             *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
    219         } else {
    220             /* XXX */
    221             *tex_format = GL_RGBA;
    222             *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
    223         }
    224         break;
    225 
    226     default:
    227         return FALSE;
    228     }
    229 
    230     if (!PICT_FORMAT_A(format))
    231         swizzle[3] = GL_ONE;
    232 
    233     return TRUE;
    234 }
    235 
    236 /**
    237  * Takes a set of source bits with a given format and returns an
    238  * in-memory pixman image of those bits in a destination format.
    239  */
    240 static pixman_image_t *
    241 glamor_get_converted_image(PictFormatShort dst_format,
    242                            PictFormatShort src_format,
    243                            void *src_bits,
    244                            int src_stride,
    245                            int w, int h)
    246 {
    247     pixman_image_t *dst_image;
    248     pixman_image_t *src_image;
    249 
    250     dst_image = pixman_image_create_bits(dst_format, w, h, NULL, 0);
    251     if (dst_image == NULL) {
    252         return NULL;
    253     }
    254 
    255     src_image = pixman_image_create_bits(src_format, w, h, src_bits, src_stride);
    256 
    257     if (src_image == NULL) {
    258         pixman_image_unref(dst_image);
    259         return NULL;
    260     }
    261 
    262     pixman_image_composite(PictOpSrc, src_image, NULL, dst_image,
    263                            0, 0, 0, 0, 0, 0, w, h);
    264 
    265     pixman_image_unref(src_image);
    266     return dst_image;
    267 }
    268 
    269 /**
    270  * Uploads a picture based on a GLAMOR_MEMORY pixmap to a texture in a
    271  * temporary FBO.
    272  */
    273 Bool
    274 glamor_upload_picture_to_texture(PicturePtr picture)
    275 {
    276     PixmapPtr pixmap = glamor_get_drawable_pixmap(picture->pDrawable);
    277     ScreenPtr screen = pixmap->drawable.pScreen;
    278     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
    279     glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
    280     PictFormatShort converted_format;
    281     void *bits = pixmap->devPrivate.ptr;
    282     int stride = pixmap->devKind;
    283     GLenum format, type;
    284     GLenum swizzle[4];
    285     GLenum iformat;
    286     Bool ret = TRUE;
    287     Bool needs_swizzle;
    288     pixman_image_t *converted_image = NULL;
    289     const struct glamor_format *f = glamor_format_for_pixmap(pixmap);
    290 
    291     assert(glamor_pixmap_is_memory(pixmap));
    292     assert(!pixmap_priv->fbo);
    293 
    294     glamor_make_current(glamor_priv);
    295 
    296     /* No handling of large pixmap pictures here (would need to make
    297      * an FBO array and split the uploads across it).
    298      */
    299     if (!glamor_check_fbo_size(glamor_priv,
    300                                pixmap->drawable.width,
    301                                pixmap->drawable.height)) {
    302         return FALSE;
    303     }
    304 
    305     if (!glamor_get_tex_format_type_from_pictformat(screen,
    306                                                     picture->format,
    307                                                     &converted_format,
    308                                                     &format,
    309                                                     &type,
    310                                                     swizzle)) {
    311         glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
    312         return FALSE;
    313     }
    314 
    315     needs_swizzle = (swizzle[0] != GL_RED ||
    316                      swizzle[1] != GL_GREEN ||
    317                      swizzle[2] != GL_BLUE ||
    318                      swizzle[3] != GL_ALPHA);
    319 
    320     if (!glamor_priv->has_texture_swizzle && needs_swizzle) {
    321         glamor_fallback("Couldn't upload temporary picture due to missing "
    322                         "GL_ARB_texture_swizzle.\n");
    323         return FALSE;
    324     }
    325 
    326     if (converted_format != picture->format) {
    327         converted_image = glamor_get_converted_image(converted_format,
    328                                                      picture->format,
    329                                                      bits, stride,
    330                                                      pixmap->drawable.width,
    331                                                      pixmap->drawable.height);
    332         if (!converted_image)
    333             return FALSE;
    334 
    335         bits = pixman_image_get_data(converted_image);
    336         stride = pixman_image_get_stride(converted_image);
    337     }
    338 
    339     if (!glamor_priv->is_gles)
    340         iformat = f->internalformat;
    341     else
    342         iformat = format;
    343 
    344     if (!glamor_pixmap_ensure_fbo(pixmap, GLAMOR_CREATE_FBO_NO_FBO)) {
    345         ret = FALSE;
    346         goto fail;
    347     }
    348 
    349     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    350 
    351     glamor_priv->suppress_gl_out_of_memory_logging = true;
    352 
    353     /* We can't use glamor_pixmap_loop() because GLAMOR_MEMORY pixmaps
    354      * don't have initialized boxes.
    355      */
    356     glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex);
    357     glTexImage2D(GL_TEXTURE_2D, 0, iformat,
    358                  pixmap->drawable.width, pixmap->drawable.height, 0,
    359                  format, type, bits);
    360 
    361     if (needs_swizzle) {
    362         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, swizzle[0]);
    363         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, swizzle[1]);
    364         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, swizzle[2]);
    365         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, swizzle[3]);
    366     }
    367 
    368     glamor_priv->suppress_gl_out_of_memory_logging = false;
    369     if (glGetError() == GL_OUT_OF_MEMORY) {
    370         ret = FALSE;
    371     }
    372 
    373 fail:
    374     if (converted_image)
    375         pixman_image_unref(converted_image);
    376 
    377     return ret;
    378 }