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