"Fossies" - the Fresh Open Source Software Archive

Member "xorg-server-1.20.8/glamor/glamor_picture.c" (29 Mar 2020, 11937 Bytes) of package /linux/misc/xorg-server-1.20.8.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "glamor_picture.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.20.7_vs_1.20.8.

    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->one_channel_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->gl_flavor == GLAMOR_GL_DESKTOP) {
   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->gl_flavor == GLAMOR_GL_DESKTOP) {
  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->gl_flavor == GLAMOR_GL_DESKTOP) {
  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->gl_flavor == GLAMOR_GL_DESKTOP) {
  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->gl_flavor == GLAMOR_GL_DESKTOP) {
  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->gl_flavor == GLAMOR_GL_DESKTOP) {
  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->gl_flavor == GLAMOR_GL_DESKTOP) {
  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->gl_flavor == GLAMOR_GL_DESKTOP) {
  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->one_channel_format;
  199         *tex_type = GL_UNSIGNED_BYTE;
  200         break;
  201 
  202     case PICT_x4r4g4b4:
  203     case PICT_a4r4g4b4:
  204         if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
  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->gl_flavor == GLAMOR_GL_DESKTOP) {
  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 
  290     assert(glamor_pixmap_is_memory(pixmap));
  291     assert(!pixmap_priv->fbo);
  292 
  293     glamor_make_current(glamor_priv);
  294 
  295     /* No handling of large pixmap pictures here (would need to make
  296      * an FBO array and split the uploads across it).
  297      */
  298     if (!glamor_check_fbo_size(glamor_priv,
  299                                pixmap->drawable.width,
  300                                pixmap->drawable.height)) {
  301         return FALSE;
  302     }
  303 
  304     if (!glamor_get_tex_format_type_from_pictformat(screen,
  305                                                     picture->format,
  306                                                     &converted_format,
  307                                                     &format,
  308                                                     &type,
  309                                                     swizzle)) {
  310         glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
  311         return FALSE;
  312     }
  313 
  314     needs_swizzle = (swizzle[0] != GL_RED ||
  315                      swizzle[1] != GL_GREEN ||
  316                      swizzle[2] != GL_BLUE ||
  317                      swizzle[3] != GL_ALPHA);
  318 
  319     if (!glamor_priv->has_texture_swizzle && needs_swizzle) {
  320         glamor_fallback("Couldn't upload temporary picture due to missing "
  321                         "GL_ARB_texture_swizzle.\n");
  322         return FALSE;
  323     }
  324 
  325     if (converted_format != picture->format) {
  326         converted_image = glamor_get_converted_image(converted_format,
  327                                                      picture->format,
  328                                                      bits, stride,
  329                                                      pixmap->drawable.width,
  330                                                      pixmap->drawable.height);
  331         if (!converted_image)
  332             return FALSE;
  333 
  334         bits = pixman_image_get_data(converted_image);
  335         stride = pixman_image_get_stride(converted_image);
  336     }
  337 
  338     if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
  339         iformat = gl_iformat_for_pixmap(pixmap);
  340     else
  341         iformat = format;
  342 
  343     if (!glamor_pixmap_ensure_fbo(pixmap, iformat, GLAMOR_CREATE_FBO_NO_FBO)) {
  344         ret = FALSE;
  345         goto fail;
  346     }
  347 
  348     glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
  349 
  350     glamor_priv->suppress_gl_out_of_memory_logging = true;
  351 
  352     /* We can't use glamor_pixmap_loop() because GLAMOR_MEMORY pixmaps
  353      * don't have initialized boxes.
  354      */
  355     glBindTexture(GL_TEXTURE_2D, pixmap_priv->fbo->tex);
  356     glTexImage2D(GL_TEXTURE_2D, 0, iformat,
  357                  pixmap->drawable.width, pixmap->drawable.height, 0,
  358                  format, type, bits);
  359 
  360     if (needs_swizzle) {
  361         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, swizzle[0]);
  362         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_G, swizzle[1]);
  363         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, swizzle[2]);
  364         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_A, swizzle[3]);
  365     }
  366 
  367     glamor_priv->suppress_gl_out_of_memory_logging = false;
  368     if (glGetError() == GL_OUT_OF_MEMORY) {
  369         ret = FALSE;
  370     }
  371 
  372 fail:
  373     if (converted_image)
  374         pixman_image_unref(converted_image);
  375 
  376     return ret;
  377 }