[PATCH 05/12] glamor: Move glamor_render.c pict handling to glamor_picture.c

Eric Anholt eric at anholt.net
Wed Jul 8 12:45:11 PDT 2015


These functions aren't used by anything else, and are specific to the
temporary-upload-as-a-weird-format path of glamor_render.c, called
through glamor_upload_picture_to_texture().

Signed-off-by: Eric Anholt <eric at anholt.net>
---
 glamor/glamor_picture.c | 870 ++++++++++++++++++++++++++++++++++++++++++++++++
 glamor/glamor_pixmap.c  | 870 ------------------------------------------------
 glamor/glamor_priv.h    |   7 -
 3 files changed, 870 insertions(+), 877 deletions(-)

diff --git a/glamor/glamor_picture.c b/glamor/glamor_picture.c
index 20b9de2..3b0b7c9 100644
--- a/glamor/glamor_picture.c
+++ b/glamor/glamor_picture.c
@@ -31,6 +31,876 @@
 #include "glamor_priv.h"
 #include "mipict.h"
 
+/*
+ * Map picture's format to the correct gl texture format and type.
+ * no_alpha is used to indicate whehter we need to wire alpha to 1.
+ *
+ * Although opengl support A1/GL_BITMAP, we still don't use it
+ * here, it seems that mesa has bugs when uploading a A1 bitmap.
+ *
+ * Return 0 if find a matched texture type. Otherwise return -1.
+ **/
+static int
+glamor_get_tex_format_type_from_pictformat_gl(PictFormatShort format,
+                                              GLenum *tex_format,
+                                              GLenum *tex_type,
+                                              int *no_alpha,
+                                              int *revert,
+                                              int *swap_rb, int is_upload)
+{
+    *no_alpha = 0;
+    *revert = REVERT_NONE;
+    *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
+    switch (format) {
+    case PICT_a1:
+        *tex_format = GL_ALPHA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
+        break;
+    case PICT_b8g8r8x8:
+        *no_alpha = 1;
+    case PICT_b8g8r8a8:
+        *tex_format = GL_BGRA;
+        *tex_type = GL_UNSIGNED_INT_8_8_8_8;
+        break;
+
+    case PICT_x8r8g8b8:
+        *no_alpha = 1;
+    case PICT_a8r8g8b8:
+        *tex_format = GL_BGRA;
+        *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+        break;
+    case PICT_x8b8g8r8:
+        *no_alpha = 1;
+    case PICT_a8b8g8r8:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
+        break;
+    case PICT_x2r10g10b10:
+        *no_alpha = 1;
+    case PICT_a2r10g10b10:
+        *tex_format = GL_BGRA;
+        *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
+        break;
+    case PICT_x2b10g10r10:
+        *no_alpha = 1;
+    case PICT_a2b10g10r10:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
+        break;
+
+    case PICT_r5g6b5:
+        *tex_format = GL_RGB;
+        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
+        break;
+    case PICT_b5g6r5:
+        *tex_format = GL_RGB;
+        *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV;
+        break;
+    case PICT_x1b5g5r5:
+        *no_alpha = 1;
+    case PICT_a1b5g5r5:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+        break;
+
+    case PICT_x1r5g5b5:
+        *no_alpha = 1;
+    case PICT_a1r5g5b5:
+        *tex_format = GL_BGRA;
+        *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
+        break;
+    case PICT_a8:
+        *tex_format = GL_ALPHA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        break;
+    case PICT_x4r4g4b4:
+        *no_alpha = 1;
+    case PICT_a4r4g4b4:
+        *tex_format = GL_BGRA;
+        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+        break;
+
+    case PICT_x4b4g4r4:
+        *no_alpha = 1;
+    case PICT_a4b4g4r4:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
+        break;
+
+    default:
+        return -1;
+    }
+    return 0;
+}
+
+#define IS_LITTLE_ENDIAN  (IMAGE_BYTE_ORDER == LSBFirst)
+
+static int
+glamor_get_tex_format_type_from_pictformat_gles2(PictFormatShort format,
+                                                 GLenum *tex_format,
+                                                 GLenum *tex_type,
+                                                 int *no_alpha,
+                                                 int *revert,
+                                                 int *swap_rb, int is_upload)
+{
+    int need_swap_rb = 0;
+
+    *no_alpha = 0;
+    *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
+
+    switch (format) {
+    case PICT_b8g8r8x8:
+        *no_alpha = 1;
+    case PICT_b8g8r8a8:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        need_swap_rb = 1;
+        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
+        break;
+
+    case PICT_x8r8g8b8:
+        *no_alpha = 1;
+    case PICT_a8r8g8b8:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        need_swap_rb = 1;
+        break;
+
+    case PICT_x8b8g8r8:
+        *no_alpha = 1;
+    case PICT_a8b8g8r8:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        break;
+
+    case PICT_x2r10g10b10:
+        *no_alpha = 1;
+    case PICT_a2r10g10b10:
+        *tex_format = GL_RGBA;
+        /* glReadPixmap doesn't support GL_UNSIGNED_INT_10_10_10_2.
+         * we have to use GL_UNSIGNED_BYTE and do the conversion in
+         * shader latter.*/
+        *tex_type = GL_UNSIGNED_BYTE;
+        if (is_upload == 1) {
+            if (!IS_LITTLE_ENDIAN)
+                *revert = REVERT_UPLOADING_10_10_10_2;
+            else
+                *revert = REVERT_UPLOADING_2_10_10_10;
+        }
+        else {
+            if (!IS_LITTLE_ENDIAN) {
+                *revert = REVERT_DOWNLOADING_10_10_10_2;
+            }
+            else {
+                *revert = REVERT_DOWNLOADING_2_10_10_10;
+            }
+        }
+        need_swap_rb = 1;
+
+        break;
+
+    case PICT_x2b10g10r10:
+        *no_alpha = 1;
+    case PICT_a2b10g10r10:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        if (is_upload == 1) {
+            if (!IS_LITTLE_ENDIAN)
+                *revert = REVERT_UPLOADING_10_10_10_2;
+            else
+                *revert = REVERT_UPLOADING_2_10_10_10;
+        }
+        else {
+            if (!IS_LITTLE_ENDIAN) {
+                *revert = REVERT_DOWNLOADING_10_10_10_2;
+            }
+            else {
+                *revert = REVERT_DOWNLOADING_2_10_10_10;
+            }
+        }
+        break;
+
+    case PICT_r5g6b5:
+        *tex_format = GL_RGB;
+        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
+        *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
+
+        break;
+
+    case PICT_b5g6r5:
+        *tex_format = GL_RGB;
+        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
+        need_swap_rb = IS_LITTLE_ENDIAN ? 1 : 0;;
+        break;
+
+    case PICT_x1b5g5r5:
+        *no_alpha = 1;
+    case PICT_a1b5g5r5:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_5_5_5_1;
+        if (IS_LITTLE_ENDIAN) {
+            *revert =
+                is_upload ? REVERT_UPLOADING_1_5_5_5 :
+                REVERT_DOWNLOADING_1_5_5_5;
+        }
+        else
+            *revert = REVERT_NONE;
+        break;
+
+    case PICT_x1r5g5b5:
+        *no_alpha = 1;
+    case PICT_a1r5g5b5:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_5_5_5_1;
+        if (IS_LITTLE_ENDIAN) {
+            *revert =
+                is_upload ? REVERT_UPLOADING_1_5_5_5 :
+                REVERT_DOWNLOADING_1_5_5_5;
+        }
+        else
+            *revert = REVERT_NONE;
+        need_swap_rb = 1;
+        break;
+
+    case PICT_a1:
+        *tex_format = GL_ALPHA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
+        break;
+
+    case PICT_a8:
+        *tex_format = GL_ALPHA;
+        *tex_type = GL_UNSIGNED_BYTE;
+        *revert = REVERT_NONE;
+        break;
+
+    case PICT_x4r4g4b4:
+        *no_alpha = 1;
+    case PICT_a4r4g4b4:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
+        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
+        need_swap_rb = 1;
+        break;
+
+    case PICT_x4b4g4r4:
+        *no_alpha = 1;
+    case PICT_a4b4g4r4:
+        *tex_format = GL_RGBA;
+        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
+        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
+        break;
+
+    default:
+        LogMessageVerb(X_INFO, 0,
+                       "fail to get matched format for %x \n", format);
+        return -1;
+    }
+
+    if (need_swap_rb)
+        *swap_rb = is_upload ? SWAP_UPLOADING : SWAP_DOWNLOADING;
+    else
+        *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
+    return 0;
+}
+
+static int
+glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
+                                       GLenum *format,
+                                       GLenum *type,
+                                       int *no_alpha,
+                                       int *revert, int *swap_rb, int is_upload)
+{
+    glamor_pixmap_private *pixmap_priv;
+    PictFormatShort pict_format;
+    glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(pixmap->drawable.pScreen);
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv))
+        pict_format = pixmap_priv->picture->format;
+    else
+        pict_format = format_for_depth(pixmap->drawable.depth);
+
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
+        return glamor_get_tex_format_type_from_pictformat_gl(pict_format,
+                                                             format, type,
+                                                             no_alpha,
+                                                             revert,
+                                                             swap_rb,
+                                                             is_upload);
+    } else {
+        return glamor_get_tex_format_type_from_pictformat_gles2(pict_format,
+                                                                format, type,
+                                                                no_alpha,
+                                                                revert,
+                                                                swap_rb,
+                                                                is_upload);
+    }
+}
+
+static void *
+_glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h,
+                            int stride, int revert)
+{
+    PictFormatShort dst_format, src_format;
+    pixman_image_t *dst_image;
+    pixman_image_t *src_image;
+    int src_stride;
+
+    if (revert == REVERT_UPLOADING_A1) {
+        src_format = PICT_a1;
+        dst_format = PICT_a8;
+        src_stride = PixmapBytePad(w, 1);
+    }
+    else {
+        dst_format = PICT_a1;
+        src_format = PICT_a8;
+        src_stride = (((w * 8 + 7) / 8) + 3) & ~3;
+    }
+
+    dst_image = pixman_image_create_bits(dst_format, w, h, dst_bits, stride);
+    if (dst_image == NULL) {
+        return NULL;
+    }
+
+    src_image = pixman_image_create_bits(src_format,
+                                         w, h, src_bits, src_stride);
+
+    if (src_image == NULL) {
+        pixman_image_unref(dst_image);
+        return NULL;
+    }
+
+    pixman_image_composite(PictOpSrc, src_image, NULL, dst_image,
+                           0, 0, 0, 0, 0, 0, w, h);
+
+    pixman_image_unref(src_image);
+    pixman_image_unref(dst_image);
+    return dst_bits;
+}
+
+#define ADJUST_BITS(d, src_bits, dst_bits)	(((dst_bits) == (src_bits)) ? (d) : 				\
+							(((dst_bits) > (src_bits)) ? 				\
+							  (((d) << ((dst_bits) - (src_bits))) 			\
+								   + (( 1 << ((dst_bits) - (src_bits))) >> 1))	\
+								:  ((d) >> ((src_bits) - (dst_bits)))))
+
+#define GLAMOR_DO_CONVERT(src, dst, no_alpha, swap,		\
+			  a_shift_src, a_bits_src,		\
+			  b_shift_src, b_bits_src,		\
+			  g_shift_src, g_bits_src,		\
+			  r_shift_src, r_bits_src,		\
+			  a_shift, a_bits,			\
+			  b_shift, b_bits,			\
+			  g_shift, g_bits,			\
+			  r_shift, r_bits)			\
+	do {								\
+		typeof(src) a,b,g,r;					\
+		typeof(src) a_mask_src, b_mask_src, g_mask_src, r_mask_src;\
+		a_mask_src = (((1 << (a_bits_src)) - 1) << a_shift_src);\
+		b_mask_src = (((1 << (b_bits_src)) - 1) << b_shift_src);\
+		g_mask_src = (((1 << (g_bits_src)) - 1) << g_shift_src);\
+		r_mask_src = (((1 << (r_bits_src)) - 1) << r_shift_src);\
+		if (no_alpha)						\
+			a = (a_mask_src) >> (a_shift_src);			\
+		else							\
+			a = ((src) & (a_mask_src)) >> (a_shift_src);	\
+		b = ((src) & (b_mask_src)) >> (b_shift_src);		\
+		g = ((src) & (g_mask_src)) >> (g_shift_src);		\
+		r = ((src) & (r_mask_src)) >> (r_shift_src);		\
+		a = ADJUST_BITS(a, a_bits_src, a_bits);			\
+		b = ADJUST_BITS(b, b_bits_src, b_bits);			\
+		g = ADJUST_BITS(g, g_bits_src, g_bits);			\
+		r = ADJUST_BITS(r, r_bits_src, r_bits);			\
+		if (swap == 0)						\
+			(*dst) = ((a) << (a_shift)) | ((b) << (b_shift)) | ((g) << (g_shift)) | ((r) << (r_shift)); \
+		else 												    \
+			(*dst) = ((a) << (a_shift)) | ((r) << (b_shift)) | ((g) << (g_shift)) | ((b) << (r_shift)); \
+	} while (0)
+
+static void *
+_glamor_color_revert_x2b10g10r10(void *src_bits, void *dst_bits, int w, int h,
+                                 int stride, int no_alpha, int revert,
+                                 int swap_rb)
+{
+    int x, y;
+    unsigned int *words, *saved_words, *source_words;
+    int swap = !(swap_rb == SWAP_NONE_DOWNLOADING ||
+                 swap_rb == SWAP_NONE_UPLOADING);
+
+    source_words = src_bits;
+    words = dst_bits;
+    saved_words = words;
+
+    for (y = 0; y < h; y++) {
+        DEBUGF("Line %d :  ", y);
+        for (x = 0; x < w; x++) {
+            unsigned int pixel = source_words[x];
+
+            if (revert == REVERT_DOWNLOADING_2_10_10_10)
+                GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
+                                  24, 8, 16, 8, 8, 8, 0, 8,
+                                  30, 2, 20, 10, 10, 10, 0, 10);
+            else
+                GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
+                                  30, 2, 20, 10, 10, 10, 0, 10,
+                                  24, 8, 16, 8, 8, 8, 0, 8);
+            DEBUGF("%x:%x ", pixel, words[x]);
+        }
+        DEBUGF("\n");
+        words += stride / sizeof(*words);
+        source_words += stride / sizeof(*words);
+    }
+    DEBUGF("\n");
+    return saved_words;
+
+}
+
+static void *
+_glamor_color_revert_x1b5g5r5(void *src_bits, void *dst_bits, int w, int h,
+                              int stride, int no_alpha, int revert, int swap_rb)
+{
+    int x, y;
+    unsigned short *words, *saved_words, *source_words;
+    int swap = !(swap_rb == SWAP_NONE_DOWNLOADING ||
+                 swap_rb == SWAP_NONE_UPLOADING);
+
+    words = dst_bits;
+    source_words = src_bits;
+    saved_words = words;
+
+    for (y = 0; y < h; y++) {
+        DEBUGF("Line %d :  ", y);
+        for (x = 0; x < w; x++) {
+            unsigned short pixel = source_words[x];
+
+            if (revert == REVERT_DOWNLOADING_1_5_5_5)
+                GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
+                                  0, 1, 1, 5, 6, 5, 11, 5,
+                                  15, 1, 10, 5, 5, 5, 0, 5);
+            else
+                GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
+                                  15, 1, 10, 5, 5, 5, 0, 5,
+                                  0, 1, 1, 5, 6, 5, 11, 5);
+            DEBUGF("%04x:%04x ", pixel, words[x]);
+        }
+        DEBUGF("\n");
+        words += stride / sizeof(*words);
+        source_words += stride / sizeof(*words);
+    }
+    DEBUGF("\n");
+    return saved_words;
+}
+
+/*
+ * This function is to convert an unsupported color format to/from a
+ * supported GL format.
+ * Here are the current scenarios:
+ *
+ * @no_alpha:
+ * 	If it is set, then we need to wire the alpha value to 1.
+ * @revert:
+	REVERT_DOWNLOADING_A1		: convert an Alpha8 buffer to a A1 buffer.
+	REVERT_UPLOADING_A1		: convert an A1 buffer to an Alpha8 buffer
+	REVERT_DOWNLOADING_2_10_10_10 	: convert r10G10b10X2 to X2B10G10R10
+	REVERT_UPLOADING_2_10_10_10 	: convert X2B10G10R10 to R10G10B10X2
+	REVERT_DOWNLOADING_1_5_5_5  	: convert B5G5R5X1 to X1R5G5B5
+	REVERT_UPLOADING_1_5_5_5    	: convert X1R5G5B5 to B5G5R5X1
+   @swap_rb: if we have the swap_rb set, then we need to swap the R and B's position.
+ *
+ */
+
+static void *
+glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h,
+                             int stride, int no_alpha, int revert, int swap_rb)
+{
+    if (revert == REVERT_DOWNLOADING_A1 || revert == REVERT_UPLOADING_A1) {
+        return _glamor_color_convert_a1_a8(src_bits, dst_bits, w, h, stride,
+                                           revert);
+    }
+    else if (revert == REVERT_DOWNLOADING_2_10_10_10 ||
+             revert == REVERT_UPLOADING_2_10_10_10) {
+        return _glamor_color_revert_x2b10g10r10(src_bits, dst_bits, w, h,
+                                                stride, no_alpha, revert,
+                                                swap_rb);
+    }
+    else if (revert == REVERT_DOWNLOADING_1_5_5_5 ||
+             revert == REVERT_UPLOADING_1_5_5_5) {
+        return _glamor_color_revert_x1b5g5r5(src_bits, dst_bits, w, h, stride,
+                                             no_alpha, revert, swap_rb);
+    }
+    else
+        ErrorF("convert a non-supported mode %x.\n", revert);
+
+    return NULL;
+}
+
+/**
+ * Upload pixmap to a specified texture.
+ * This texture may not be the one attached to it.
+ **/
+static void
+__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
+                                  GLenum format,
+                                  GLenum type,
+                                  int x, int y, int w, int h,
+                                  void *bits, int pbo)
+{
+    glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(pixmap->drawable.pScreen);
+    int non_sub = 0;
+    unsigned int iformat = 0;
+
+    glamor_make_current(glamor_priv);
+    if (*tex == 0) {
+        glGenTextures(1, tex);
+        if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
+            iformat = gl_iformat_for_pixmap(pixmap);
+        else
+            iformat = format;
+        non_sub = 1;
+        assert(x == 0 && y == 0);
+    }
+
+    glBindTexture(GL_TEXTURE_2D, *tex);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+
+    assert(pbo || bits != 0);
+    if (bits == NULL) {
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
+        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
+    }
+    if (non_sub)
+        glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits);
+    else
+        glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, format, type, bits);
+
+    if (bits == NULL)
+        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
+}
+
+static Bool
+_glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
+                                      GLenum type, int no_alpha, int revert,
+                                      int swap_rb, int x, int y, int w, int h,
+                                      int stride, void *bits, int pbo)
+{
+    ScreenPtr screen = pixmap->drawable.pScreen;
+    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+    glamor_screen_private *glamor_priv =
+        glamor_get_screen_private(pixmap->drawable.pScreen);
+    static float vertices[8];
+
+    static float texcoords_inv[8] = { 0, 0,
+        1, 0,
+        1, 1,
+        0, 1
+    };
+    float *ptexcoords;
+    float dst_xscale, dst_yscale;
+    GLuint tex = 0;
+    int need_free_bits = 0;
+
+    if (bits == NULL)
+        goto ready_to_upload;
+
+    if (revert > REVERT_NORMAL) {
+        /* XXX if we are restoring the pixmap, then we may not need to allocate
+         * new buffer */
+        void *converted_bits;
+
+        if (pixmap->drawable.depth == 1)
+            stride = (((w * 8 + 7) / 8) + 3) & ~3;
+
+        converted_bits = xallocarray(h, stride);
+
+        if (converted_bits == NULL)
+            return FALSE;
+        bits = glamor_color_convert_to_bits(bits, converted_bits, w, h,
+                                            stride, no_alpha, revert, swap_rb);
+        if (bits == NULL) {
+            free(converted_bits);
+            ErrorF("Failed to convert pixmap no_alpha %d,"
+                   "revert mode %d, swap mode %d\n", no_alpha, revert, swap_rb);
+            return FALSE;
+        }
+        no_alpha = 0;
+        revert = REVERT_NONE;
+        swap_rb = SWAP_NONE_UPLOADING;
+        need_free_bits = TRUE;
+    }
+
+ ready_to_upload:
+
+    /* Try fast path firstly, upload the pixmap to the texture attached
+     * to the fbo directly. */
+    if (no_alpha == 0
+        && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING
+#ifdef WALKAROUND_LARGE_TEXTURE_MAP
+        && glamor_pixmap_priv_is_small(pixmap_priv)
+#endif
+        ) {
+        int fbo_x_off, fbo_y_off;
+
+        assert(pixmap_priv->fbo->tex);
+        pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off);
+
+        assert(x + fbo_x_off >= 0 && y + fbo_y_off >= 0);
+        assert(x + fbo_x_off + w <= pixmap_priv->fbo->width);
+        assert(y + fbo_y_off + h <= pixmap_priv->fbo->height);
+        __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->fbo->tex,
+                                          format, type,
+                                          x + fbo_x_off, y + fbo_y_off, w, h,
+                                          bits, pbo);
+    } else {
+        ptexcoords = texcoords_inv;
+
+        pixmap_priv_get_dest_scale(pixmap, pixmap_priv, &dst_xscale, &dst_yscale);
+        glamor_set_normalize_vcoords(pixmap_priv, dst_xscale,
+                                     dst_yscale,
+                                     x, y,
+                                     x + w, y + h,
+                                     vertices);
+        /* Slow path, we need to flip y or wire alpha to 1. */
+        glamor_make_current(glamor_priv);
+        glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
+                              GL_FALSE, 2 * sizeof(float), vertices);
+        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
+        glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
+                              GL_FALSE, 2 * sizeof(float), ptexcoords);
+        glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+
+        glamor_set_destination_pixmap_priv_nc(glamor_priv, pixmap, pixmap_priv);
+        glamor_set_alu(screen, GXcopy);
+        __glamor_upload_pixmap_to_texture(pixmap, &tex,
+                                          format, type, 0, 0, w, h, bits, pbo);
+        glActiveTexture(GL_TEXTURE0);
+        glBindTexture(GL_TEXTURE_2D, tex);
+
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+        glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
+        glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
+        glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb);
+
+        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+        glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
+        glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
+        glDeleteTextures(1, &tex);
+        glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    }
+
+    if (need_free_bits)
+        free(bits);
+    return TRUE;
+}
+
+/*
+ * Prepare to upload a pixmap to texture memory.
+ * no_alpha equals 1 means the format needs to wire alpha to 1.
+ */
+static int
+glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha,
+                             int revert, int swap_rb)
+{
+    int flag = 0;
+    glamor_pixmap_private *pixmap_priv;
+    glamor_screen_private *glamor_priv;
+    glamor_pixmap_fbo *fbo;
+    GLenum iformat;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
+
+    if (pixmap_priv->gl_fbo != GLAMOR_FBO_UNATTACHED)
+        return 0;
+
+    if (pixmap_priv->fbo
+        && (pixmap_priv->fbo->width < pixmap->drawable.width
+            || pixmap_priv->fbo->height < pixmap->drawable.height)) {
+        fbo = glamor_pixmap_detach_fbo(pixmap_priv);
+        glamor_destroy_fbo(glamor_priv, fbo);
+    }
+
+    if (pixmap_priv->fbo && pixmap_priv->fbo->fb)
+        return 0;
+
+    if (!(no_alpha || (revert == REVERT_NORMAL)
+          || (swap_rb != SWAP_NONE_UPLOADING))) {
+        /* We don't need a fbo, a simple texture uploading should work. */
+
+        flag = GLAMOR_CREATE_FBO_NO_FBO;
+    }
+
+    if ((flag == GLAMOR_CREATE_FBO_NO_FBO
+         && pixmap_priv->fbo && pixmap_priv->fbo->tex))
+        return 0;
+
+    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
+        iformat = gl_iformat_for_pixmap(pixmap);
+    else
+        iformat = format;
+
+    if (!glamor_pixmap_ensure_fbo(pixmap, iformat, flag))
+        return -1;
+
+    return 0;
+}
+
+/*
+ * upload sub region to a large region.
+ * */
+static void
+glamor_put_bits(char *dst_bits, int dst_stride, char *src_bits,
+                int src_stride, int bpp, int x, int y, int w, int h)
+{
+    int j;
+    int byte_per_pixel;
+
+    byte_per_pixel = bpp / 8;
+    src_bits += y * src_stride + (x * byte_per_pixel);
+
+    for (j = y; j < y + h; j++) {
+        memcpy(dst_bits, src_bits, w * byte_per_pixel);
+        src_bits += src_stride;
+        dst_bits += dst_stride;
+    }
+}
+
+static Bool
+glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w,
+                                    int h, int stride, void *bits, int pbo)
+{
+    ScreenPtr screen = pixmap->drawable.pScreen;
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
+    GLenum format, type;
+    int no_alpha, revert, swap_rb;
+    glamor_pixmap_private *pixmap_priv;
+    Bool force_clip;
+
+    if (glamor_get_tex_format_type_from_pixmap(pixmap,
+                                               &format,
+                                               &type,
+                                               &no_alpha,
+                                               &revert, &swap_rb, 1)) {
+        glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
+        return FALSE;
+    }
+    if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb))
+        return FALSE;
+
+    pixmap_priv = glamor_get_pixmap_private(pixmap);
+    force_clip = glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP
+        && !glamor_check_fbo_size(glamor_priv, w, h);
+
+    if (glamor_pixmap_priv_is_large(pixmap_priv) || force_clip) {
+        RegionRec region;
+        BoxRec box;
+        int n_region;
+        glamor_pixmap_clipped_regions *clipped_regions;
+        void *sub_bits;
+        int i, j;
+
+        sub_bits = xallocarray(h, stride);
+        if (sub_bits == NULL)
+            return FALSE;
+        box.x1 = x;
+        box.y1 = y;
+        box.x2 = x + w;
+        box.y2 = y + h;
+        RegionInitBoxes(&region, &box, 1);
+        if (!force_clip)
+            clipped_regions =
+                glamor_compute_clipped_regions(pixmap, &region, &n_region,
+                                               0, 0, 0);
+        else
+            clipped_regions =
+                glamor_compute_clipped_regions_ext(pixmap, &region,
+                                                   &n_region,
+                                                   pixmap_priv->block_w,
+                                                   pixmap_priv->block_h,
+                                                   0,
+                                                   0);
+        DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap);
+        for (i = 0; i < n_region; i++) {
+            BoxPtr boxes;
+            int nbox;
+            int temp_stride;
+            void *temp_bits;
+
+            assert(pbo == 0);
+
+            glamor_set_pixmap_fbo_current(pixmap_priv, clipped_regions[i].block_idx);
+
+            boxes = RegionRects(clipped_regions[i].region);
+            nbox = RegionNumRects(clipped_regions[i].region);
+            DEBUGF("split to %d boxes\n", nbox);
+            for (j = 0; j < nbox; j++) {
+                temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1,
+                                            pixmap->drawable.depth);
+
+                if (boxes[j].x1 == x && temp_stride == stride) {
+                    temp_bits = (char *) bits + (boxes[j].y1 - y) * stride;
+                }
+                else {
+                    temp_bits = sub_bits;
+                    glamor_put_bits(temp_bits, temp_stride, bits, stride,
+                                    pixmap->drawable.bitsPerPixel,
+                                    boxes[j].x1 - x, boxes[j].y1 - y,
+                                    boxes[j].x2 - boxes[j].x1,
+                                    boxes[j].y2 - boxes[j].y1);
+                }
+                DEBUGF("upload x %d y %d w %d h %d temp stride %d \n",
+                       boxes[j].x1 - x, boxes[j].y1 - y,
+                       boxes[j].x2 - boxes[j].x1,
+                       boxes[j].y2 - boxes[j].y1, temp_stride);
+                if (_glamor_upload_bits_to_pixmap_texture
+                    (pixmap, format, type, no_alpha, revert, swap_rb,
+                     boxes[j].x1, boxes[j].y1, boxes[j].x2 - boxes[j].x1,
+                     boxes[j].y2 - boxes[j].y1, temp_stride, temp_bits,
+                     pbo) == FALSE) {
+                    RegionUninit(&region);
+                    free(sub_bits);
+                    assert(0);
+                    return FALSE;
+                }
+            }
+            RegionDestroy(clipped_regions[i].region);
+        }
+        free(sub_bits);
+        free(clipped_regions);
+        RegionUninit(&region);
+        return TRUE;
+    }
+    else
+        return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type,
+                                                     no_alpha, revert, swap_rb,
+                                                     x, y, w, h, stride, bits,
+                                                     pbo);
+}
+
+static enum glamor_pixmap_status
+glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
+{
+    int ret;
+
+    if (glamor_upload_sub_pixmap_to_texture(pixmap, 0, 0,
+                                            pixmap->drawable.width,
+                                            pixmap->drawable.height,
+                                            pixmap->devKind,
+                                            pixmap->devPrivate.ptr, 0))
+        ret = GLAMOR_UPLOAD_DONE;
+    else
+        ret = GLAMOR_UPLOAD_FAILED;
+
+    return ret;
+}
+
 /* Upload picture to texture.  We may need to flip the y axis or
  * wire alpha to 1. So we may conditional create fbo for the picture.
  * */
diff --git a/glamor/glamor_pixmap.c b/glamor/glamor_pixmap.c
index 5a09d32..166bde5 100644
--- a/glamor/glamor_pixmap.c
+++ b/glamor/glamor_pixmap.c
@@ -189,873 +189,3 @@ glamor_set_alu(ScreenPtr screen, unsigned char alu)
 
     return TRUE;
 }
-
-/*
- * Map picture's format to the correct gl texture format and type.
- * no_alpha is used to indicate whehter we need to wire alpha to 1.
- *
- * Although opengl support A1/GL_BITMAP, we still don't use it
- * here, it seems that mesa has bugs when uploading a A1 bitmap.
- *
- * Return 0 if find a matched texture type. Otherwise return -1.
- **/
-static int
-glamor_get_tex_format_type_from_pictformat_gl(PictFormatShort format,
-                                              GLenum *tex_format,
-                                              GLenum *tex_type,
-                                              int *no_alpha,
-                                              int *revert,
-                                              int *swap_rb, int is_upload)
-{
-    *no_alpha = 0;
-    *revert = REVERT_NONE;
-    *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
-    switch (format) {
-    case PICT_a1:
-        *tex_format = GL_ALPHA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
-        break;
-    case PICT_b8g8r8x8:
-        *no_alpha = 1;
-    case PICT_b8g8r8a8:
-        *tex_format = GL_BGRA;
-        *tex_type = GL_UNSIGNED_INT_8_8_8_8;
-        break;
-
-    case PICT_x8r8g8b8:
-        *no_alpha = 1;
-    case PICT_a8r8g8b8:
-        *tex_format = GL_BGRA;
-        *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
-        break;
-    case PICT_x8b8g8r8:
-        *no_alpha = 1;
-    case PICT_a8b8g8r8:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_INT_8_8_8_8_REV;
-        break;
-    case PICT_x2r10g10b10:
-        *no_alpha = 1;
-    case PICT_a2r10g10b10:
-        *tex_format = GL_BGRA;
-        *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
-        break;
-    case PICT_x2b10g10r10:
-        *no_alpha = 1;
-    case PICT_a2b10g10r10:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_INT_2_10_10_10_REV;
-        break;
-
-    case PICT_r5g6b5:
-        *tex_format = GL_RGB;
-        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
-        break;
-    case PICT_b5g6r5:
-        *tex_format = GL_RGB;
-        *tex_type = GL_UNSIGNED_SHORT_5_6_5_REV;
-        break;
-    case PICT_x1b5g5r5:
-        *no_alpha = 1;
-    case PICT_a1b5g5r5:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
-        break;
-
-    case PICT_x1r5g5b5:
-        *no_alpha = 1;
-    case PICT_a1r5g5b5:
-        *tex_format = GL_BGRA;
-        *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
-        break;
-    case PICT_a8:
-        *tex_format = GL_ALPHA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        break;
-    case PICT_x4r4g4b4:
-        *no_alpha = 1;
-    case PICT_a4r4g4b4:
-        *tex_format = GL_BGRA;
-        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
-        break;
-
-    case PICT_x4b4g4r4:
-        *no_alpha = 1;
-    case PICT_a4b4g4r4:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
-        break;
-
-    default:
-        return -1;
-    }
-    return 0;
-}
-
-#define IS_LITTLE_ENDIAN  (IMAGE_BYTE_ORDER == LSBFirst)
-
-static int
-glamor_get_tex_format_type_from_pictformat_gles2(PictFormatShort format,
-                                                 GLenum *tex_format,
-                                                 GLenum *tex_type,
-                                                 int *no_alpha,
-                                                 int *revert,
-                                                 int *swap_rb, int is_upload)
-{
-    int need_swap_rb = 0;
-
-    *no_alpha = 0;
-    *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
-
-    switch (format) {
-    case PICT_b8g8r8x8:
-        *no_alpha = 1;
-    case PICT_b8g8r8a8:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        need_swap_rb = 1;
-        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
-        break;
-
-    case PICT_x8r8g8b8:
-        *no_alpha = 1;
-    case PICT_a8r8g8b8:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        need_swap_rb = 1;
-        break;
-
-    case PICT_x8b8g8r8:
-        *no_alpha = 1;
-    case PICT_a8b8g8r8:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        break;
-
-    case PICT_x2r10g10b10:
-        *no_alpha = 1;
-    case PICT_a2r10g10b10:
-        *tex_format = GL_RGBA;
-        /* glReadPixmap doesn't support GL_UNSIGNED_INT_10_10_10_2.
-         * we have to use GL_UNSIGNED_BYTE and do the conversion in
-         * shader latter.*/
-        *tex_type = GL_UNSIGNED_BYTE;
-        if (is_upload == 1) {
-            if (!IS_LITTLE_ENDIAN)
-                *revert = REVERT_UPLOADING_10_10_10_2;
-            else
-                *revert = REVERT_UPLOADING_2_10_10_10;
-        }
-        else {
-            if (!IS_LITTLE_ENDIAN) {
-                *revert = REVERT_DOWNLOADING_10_10_10_2;
-            }
-            else {
-                *revert = REVERT_DOWNLOADING_2_10_10_10;
-            }
-        }
-        need_swap_rb = 1;
-
-        break;
-
-    case PICT_x2b10g10r10:
-        *no_alpha = 1;
-    case PICT_a2b10g10r10:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        if (is_upload == 1) {
-            if (!IS_LITTLE_ENDIAN)
-                *revert = REVERT_UPLOADING_10_10_10_2;
-            else
-                *revert = REVERT_UPLOADING_2_10_10_10;
-        }
-        else {
-            if (!IS_LITTLE_ENDIAN) {
-                *revert = REVERT_DOWNLOADING_10_10_10_2;
-            }
-            else {
-                *revert = REVERT_DOWNLOADING_2_10_10_10;
-            }
-        }
-        break;
-
-    case PICT_r5g6b5:
-        *tex_format = GL_RGB;
-        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
-        *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
-
-        break;
-
-    case PICT_b5g6r5:
-        *tex_format = GL_RGB;
-        *tex_type = GL_UNSIGNED_SHORT_5_6_5;
-        need_swap_rb = IS_LITTLE_ENDIAN ? 1 : 0;;
-        break;
-
-    case PICT_x1b5g5r5:
-        *no_alpha = 1;
-    case PICT_a1b5g5r5:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_5_5_5_1;
-        if (IS_LITTLE_ENDIAN) {
-            *revert =
-                is_upload ? REVERT_UPLOADING_1_5_5_5 :
-                REVERT_DOWNLOADING_1_5_5_5;
-        }
-        else
-            *revert = REVERT_NONE;
-        break;
-
-    case PICT_x1r5g5b5:
-        *no_alpha = 1;
-    case PICT_a1r5g5b5:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_5_5_5_1;
-        if (IS_LITTLE_ENDIAN) {
-            *revert =
-                is_upload ? REVERT_UPLOADING_1_5_5_5 :
-                REVERT_DOWNLOADING_1_5_5_5;
-        }
-        else
-            *revert = REVERT_NONE;
-        need_swap_rb = 1;
-        break;
-
-    case PICT_a1:
-        *tex_format = GL_ALPHA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        *revert = is_upload ? REVERT_UPLOADING_A1 : REVERT_DOWNLOADING_A1;
-        break;
-
-    case PICT_a8:
-        *tex_format = GL_ALPHA;
-        *tex_type = GL_UNSIGNED_BYTE;
-        *revert = REVERT_NONE;
-        break;
-
-    case PICT_x4r4g4b4:
-        *no_alpha = 1;
-    case PICT_a4r4g4b4:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
-        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
-        need_swap_rb = 1;
-        break;
-
-    case PICT_x4b4g4r4:
-        *no_alpha = 1;
-    case PICT_a4b4g4r4:
-        *tex_format = GL_RGBA;
-        *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
-        *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
-        break;
-
-    default:
-        LogMessageVerb(X_INFO, 0,
-                       "fail to get matched format for %x \n", format);
-        return -1;
-    }
-
-    if (need_swap_rb)
-        *swap_rb = is_upload ? SWAP_UPLOADING : SWAP_DOWNLOADING;
-    else
-        *swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
-    return 0;
-}
-
-static int
-glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
-                                       GLenum *format,
-                                       GLenum *type,
-                                       int *no_alpha,
-                                       int *revert, int *swap_rb, int is_upload)
-{
-    glamor_pixmap_private *pixmap_priv;
-    PictFormatShort pict_format;
-    glamor_screen_private *glamor_priv =
-        glamor_get_screen_private(pixmap->drawable.pScreen);
-
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-    if (GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv))
-        pict_format = pixmap_priv->picture->format;
-    else
-        pict_format = format_for_depth(pixmap->drawable.depth);
-
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
-        return glamor_get_tex_format_type_from_pictformat_gl(pict_format,
-                                                             format, type,
-                                                             no_alpha,
-                                                             revert,
-                                                             swap_rb,
-                                                             is_upload);
-    } else {
-        return glamor_get_tex_format_type_from_pictformat_gles2(pict_format,
-                                                                format, type,
-                                                                no_alpha,
-                                                                revert,
-                                                                swap_rb,
-                                                                is_upload);
-    }
-}
-
-static void *
-_glamor_color_convert_a1_a8(void *src_bits, void *dst_bits, int w, int h,
-                            int stride, int revert)
-{
-    PictFormatShort dst_format, src_format;
-    pixman_image_t *dst_image;
-    pixman_image_t *src_image;
-    int src_stride;
-
-    if (revert == REVERT_UPLOADING_A1) {
-        src_format = PICT_a1;
-        dst_format = PICT_a8;
-        src_stride = PixmapBytePad(w, 1);
-    }
-    else {
-        dst_format = PICT_a1;
-        src_format = PICT_a8;
-        src_stride = (((w * 8 + 7) / 8) + 3) & ~3;
-    }
-
-    dst_image = pixman_image_create_bits(dst_format, w, h, dst_bits, stride);
-    if (dst_image == NULL) {
-        return NULL;
-    }
-
-    src_image = pixman_image_create_bits(src_format,
-                                         w, h, src_bits, src_stride);
-
-    if (src_image == NULL) {
-        pixman_image_unref(dst_image);
-        return NULL;
-    }
-
-    pixman_image_composite(PictOpSrc, src_image, NULL, dst_image,
-                           0, 0, 0, 0, 0, 0, w, h);
-
-    pixman_image_unref(src_image);
-    pixman_image_unref(dst_image);
-    return dst_bits;
-}
-
-#define ADJUST_BITS(d, src_bits, dst_bits)	(((dst_bits) == (src_bits)) ? (d) : 				\
-							(((dst_bits) > (src_bits)) ? 				\
-							  (((d) << ((dst_bits) - (src_bits))) 			\
-								   + (( 1 << ((dst_bits) - (src_bits))) >> 1))	\
-								:  ((d) >> ((src_bits) - (dst_bits)))))
-
-#define GLAMOR_DO_CONVERT(src, dst, no_alpha, swap,		\
-			  a_shift_src, a_bits_src,		\
-			  b_shift_src, b_bits_src,		\
-			  g_shift_src, g_bits_src,		\
-			  r_shift_src, r_bits_src,		\
-			  a_shift, a_bits,			\
-			  b_shift, b_bits,			\
-			  g_shift, g_bits,			\
-			  r_shift, r_bits)			\
-	do {								\
-		typeof(src) a,b,g,r;					\
-		typeof(src) a_mask_src, b_mask_src, g_mask_src, r_mask_src;\
-		a_mask_src = (((1 << (a_bits_src)) - 1) << a_shift_src);\
-		b_mask_src = (((1 << (b_bits_src)) - 1) << b_shift_src);\
-		g_mask_src = (((1 << (g_bits_src)) - 1) << g_shift_src);\
-		r_mask_src = (((1 << (r_bits_src)) - 1) << r_shift_src);\
-		if (no_alpha)						\
-			a = (a_mask_src) >> (a_shift_src);			\
-		else							\
-			a = ((src) & (a_mask_src)) >> (a_shift_src);	\
-		b = ((src) & (b_mask_src)) >> (b_shift_src);		\
-		g = ((src) & (g_mask_src)) >> (g_shift_src);		\
-		r = ((src) & (r_mask_src)) >> (r_shift_src);		\
-		a = ADJUST_BITS(a, a_bits_src, a_bits);			\
-		b = ADJUST_BITS(b, b_bits_src, b_bits);			\
-		g = ADJUST_BITS(g, g_bits_src, g_bits);			\
-		r = ADJUST_BITS(r, r_bits_src, r_bits);			\
-		if (swap == 0)						\
-			(*dst) = ((a) << (a_shift)) | ((b) << (b_shift)) | ((g) << (g_shift)) | ((r) << (r_shift)); \
-		else 												    \
-			(*dst) = ((a) << (a_shift)) | ((r) << (b_shift)) | ((g) << (g_shift)) | ((b) << (r_shift)); \
-	} while (0)
-
-static void *
-_glamor_color_revert_x2b10g10r10(void *src_bits, void *dst_bits, int w, int h,
-                                 int stride, int no_alpha, int revert,
-                                 int swap_rb)
-{
-    int x, y;
-    unsigned int *words, *saved_words, *source_words;
-    int swap = !(swap_rb == SWAP_NONE_DOWNLOADING ||
-                 swap_rb == SWAP_NONE_UPLOADING);
-
-    source_words = src_bits;
-    words = dst_bits;
-    saved_words = words;
-
-    for (y = 0; y < h; y++) {
-        DEBUGF("Line %d :  ", y);
-        for (x = 0; x < w; x++) {
-            unsigned int pixel = source_words[x];
-
-            if (revert == REVERT_DOWNLOADING_2_10_10_10)
-                GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
-                                  24, 8, 16, 8, 8, 8, 0, 8,
-                                  30, 2, 20, 10, 10, 10, 0, 10);
-            else
-                GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
-                                  30, 2, 20, 10, 10, 10, 0, 10,
-                                  24, 8, 16, 8, 8, 8, 0, 8);
-            DEBUGF("%x:%x ", pixel, words[x]);
-        }
-        DEBUGF("\n");
-        words += stride / sizeof(*words);
-        source_words += stride / sizeof(*words);
-    }
-    DEBUGF("\n");
-    return saved_words;
-
-}
-
-static void *
-_glamor_color_revert_x1b5g5r5(void *src_bits, void *dst_bits, int w, int h,
-                              int stride, int no_alpha, int revert, int swap_rb)
-{
-    int x, y;
-    unsigned short *words, *saved_words, *source_words;
-    int swap = !(swap_rb == SWAP_NONE_DOWNLOADING ||
-                 swap_rb == SWAP_NONE_UPLOADING);
-
-    words = dst_bits;
-    source_words = src_bits;
-    saved_words = words;
-
-    for (y = 0; y < h; y++) {
-        DEBUGF("Line %d :  ", y);
-        for (x = 0; x < w; x++) {
-            unsigned short pixel = source_words[x];
-
-            if (revert == REVERT_DOWNLOADING_1_5_5_5)
-                GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
-                                  0, 1, 1, 5, 6, 5, 11, 5,
-                                  15, 1, 10, 5, 5, 5, 0, 5);
-            else
-                GLAMOR_DO_CONVERT(pixel, &words[x], no_alpha, swap,
-                                  15, 1, 10, 5, 5, 5, 0, 5,
-                                  0, 1, 1, 5, 6, 5, 11, 5);
-            DEBUGF("%04x:%04x ", pixel, words[x]);
-        }
-        DEBUGF("\n");
-        words += stride / sizeof(*words);
-        source_words += stride / sizeof(*words);
-    }
-    DEBUGF("\n");
-    return saved_words;
-}
-
-/*
- * This function is to convert an unsupported color format to/from a
- * supported GL format.
- * Here are the current scenarios:
- *
- * @no_alpha:
- * 	If it is set, then we need to wire the alpha value to 1.
- * @revert:
-	REVERT_DOWNLOADING_A1		: convert an Alpha8 buffer to a A1 buffer.
-	REVERT_UPLOADING_A1		: convert an A1 buffer to an Alpha8 buffer
-	REVERT_DOWNLOADING_2_10_10_10 	: convert r10G10b10X2 to X2B10G10R10
-	REVERT_UPLOADING_2_10_10_10 	: convert X2B10G10R10 to R10G10B10X2
-	REVERT_DOWNLOADING_1_5_5_5  	: convert B5G5R5X1 to X1R5G5B5
-	REVERT_UPLOADING_1_5_5_5    	: convert X1R5G5B5 to B5G5R5X1
-   @swap_rb: if we have the swap_rb set, then we need to swap the R and B's position.
- *
- */
-
-static void *
-glamor_color_convert_to_bits(void *src_bits, void *dst_bits, int w, int h,
-                             int stride, int no_alpha, int revert, int swap_rb)
-{
-    if (revert == REVERT_DOWNLOADING_A1 || revert == REVERT_UPLOADING_A1) {
-        return _glamor_color_convert_a1_a8(src_bits, dst_bits, w, h, stride,
-                                           revert);
-    }
-    else if (revert == REVERT_DOWNLOADING_2_10_10_10 ||
-             revert == REVERT_UPLOADING_2_10_10_10) {
-        return _glamor_color_revert_x2b10g10r10(src_bits, dst_bits, w, h,
-                                                stride, no_alpha, revert,
-                                                swap_rb);
-    }
-    else if (revert == REVERT_DOWNLOADING_1_5_5_5 ||
-             revert == REVERT_UPLOADING_1_5_5_5) {
-        return _glamor_color_revert_x1b5g5r5(src_bits, dst_bits, w, h, stride,
-                                             no_alpha, revert, swap_rb);
-    }
-    else
-        ErrorF("convert a non-supported mode %x.\n", revert);
-
-    return NULL;
-}
-
-/**
- * Upload pixmap to a specified texture.
- * This texture may not be the one attached to it.
- **/
-static void
-__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, unsigned int *tex,
-                                  GLenum format,
-                                  GLenum type,
-                                  int x, int y, int w, int h,
-                                  void *bits, int pbo)
-{
-    glamor_screen_private *glamor_priv =
-        glamor_get_screen_private(pixmap->drawable.pScreen);
-    int non_sub = 0;
-    unsigned int iformat = 0;
-
-    glamor_make_current(glamor_priv);
-    if (*tex == 0) {
-        glGenTextures(1, tex);
-        if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-            iformat = gl_iformat_for_pixmap(pixmap);
-        else
-            iformat = format;
-        non_sub = 1;
-        assert(x == 0 && y == 0);
-    }
-
-    glBindTexture(GL_TEXTURE_2D, *tex);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
-
-    assert(pbo || bits != 0);
-    if (bits == NULL) {
-        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, pbo);
-        glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
-    }
-    if (non_sub)
-        glTexImage2D(GL_TEXTURE_2D, 0, iformat, w, h, 0, format, type, bits);
-    else
-        glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, w, h, format, type, bits);
-
-    if (bits == NULL)
-        glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
-}
-
-static Bool
-_glamor_upload_bits_to_pixmap_texture(PixmapPtr pixmap, GLenum format,
-                                      GLenum type, int no_alpha, int revert,
-                                      int swap_rb, int x, int y, int w, int h,
-                                      int stride, void *bits, int pbo)
-{
-    ScreenPtr screen = pixmap->drawable.pScreen;
-    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
-    glamor_screen_private *glamor_priv =
-        glamor_get_screen_private(pixmap->drawable.pScreen);
-    static float vertices[8];
-
-    static float texcoords_inv[8] = { 0, 0,
-        1, 0,
-        1, 1,
-        0, 1
-    };
-    float *ptexcoords;
-    float dst_xscale, dst_yscale;
-    GLuint tex = 0;
-    int need_free_bits = 0;
-
-    if (bits == NULL)
-        goto ready_to_upload;
-
-    if (revert > REVERT_NORMAL) {
-        /* XXX if we are restoring the pixmap, then we may not need to allocate
-         * new buffer */
-        void *converted_bits;
-
-        if (pixmap->drawable.depth == 1)
-            stride = (((w * 8 + 7) / 8) + 3) & ~3;
-
-        converted_bits = xallocarray(h, stride);
-
-        if (converted_bits == NULL)
-            return FALSE;
-        bits = glamor_color_convert_to_bits(bits, converted_bits, w, h,
-                                            stride, no_alpha, revert, swap_rb);
-        if (bits == NULL) {
-            free(converted_bits);
-            ErrorF("Failed to convert pixmap no_alpha %d,"
-                   "revert mode %d, swap mode %d\n", no_alpha, revert, swap_rb);
-            return FALSE;
-        }
-        no_alpha = 0;
-        revert = REVERT_NONE;
-        swap_rb = SWAP_NONE_UPLOADING;
-        need_free_bits = TRUE;
-    }
-
- ready_to_upload:
-
-    /* Try fast path firstly, upload the pixmap to the texture attached
-     * to the fbo directly. */
-    if (no_alpha == 0
-        && revert == REVERT_NONE && swap_rb == SWAP_NONE_UPLOADING
-#ifdef WALKAROUND_LARGE_TEXTURE_MAP
-        && glamor_pixmap_priv_is_small(pixmap_priv)
-#endif
-        ) {
-        int fbo_x_off, fbo_y_off;
-
-        assert(pixmap_priv->fbo->tex);
-        pixmap_priv_get_fbo_off(pixmap_priv, &fbo_x_off, &fbo_y_off);
-
-        assert(x + fbo_x_off >= 0 && y + fbo_y_off >= 0);
-        assert(x + fbo_x_off + w <= pixmap_priv->fbo->width);
-        assert(y + fbo_y_off + h <= pixmap_priv->fbo->height);
-        __glamor_upload_pixmap_to_texture(pixmap, &pixmap_priv->fbo->tex,
-                                          format, type,
-                                          x + fbo_x_off, y + fbo_y_off, w, h,
-                                          bits, pbo);
-    } else {
-        ptexcoords = texcoords_inv;
-
-        pixmap_priv_get_dest_scale(pixmap, pixmap_priv, &dst_xscale, &dst_yscale);
-        glamor_set_normalize_vcoords(pixmap_priv, dst_xscale,
-                                     dst_yscale,
-                                     x, y,
-                                     x + w, y + h,
-                                     vertices);
-        /* Slow path, we need to flip y or wire alpha to 1. */
-        glamor_make_current(glamor_priv);
-        glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
-                              GL_FALSE, 2 * sizeof(float), vertices);
-        glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
-        glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
-                              GL_FALSE, 2 * sizeof(float), ptexcoords);
-        glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-
-        glamor_set_destination_pixmap_priv_nc(glamor_priv, pixmap, pixmap_priv);
-        glamor_set_alu(screen, GXcopy);
-        __glamor_upload_pixmap_to_texture(pixmap, &tex,
-                                          format, type, 0, 0, w, h, bits, pbo);
-        glActiveTexture(GL_TEXTURE0);
-        glBindTexture(GL_TEXTURE_2D, tex);
-
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-        glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
-        glUniform1i(glamor_priv->finish_access_revert[no_alpha], revert);
-        glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], swap_rb);
-
-        glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
-
-        glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
-        glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
-        glDeleteTextures(1, &tex);
-        glBindFramebuffer(GL_FRAMEBUFFER, 0);
-    }
-
-    if (need_free_bits)
-        free(bits);
-    return TRUE;
-}
-
-/*
- * Prepare to upload a pixmap to texture memory.
- * no_alpha equals 1 means the format needs to wire alpha to 1.
- */
-static int
-glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha,
-                             int revert, int swap_rb)
-{
-    int flag = 0;
-    glamor_pixmap_private *pixmap_priv;
-    glamor_screen_private *glamor_priv;
-    glamor_pixmap_fbo *fbo;
-    GLenum iformat;
-
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-    glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
-
-    if (pixmap_priv->gl_fbo != GLAMOR_FBO_UNATTACHED)
-        return 0;
-
-    if (pixmap_priv->fbo
-        && (pixmap_priv->fbo->width < pixmap->drawable.width
-            || pixmap_priv->fbo->height < pixmap->drawable.height)) {
-        fbo = glamor_pixmap_detach_fbo(pixmap_priv);
-        glamor_destroy_fbo(glamor_priv, fbo);
-    }
-
-    if (pixmap_priv->fbo && pixmap_priv->fbo->fb)
-        return 0;
-
-    if (!(no_alpha || (revert == REVERT_NORMAL)
-          || (swap_rb != SWAP_NONE_UPLOADING))) {
-        /* We don't need a fbo, a simple texture uploading should work. */
-
-        flag = GLAMOR_CREATE_FBO_NO_FBO;
-    }
-
-    if ((flag == GLAMOR_CREATE_FBO_NO_FBO
-         && pixmap_priv->fbo && pixmap_priv->fbo->tex))
-        return 0;
-
-    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
-        iformat = gl_iformat_for_pixmap(pixmap);
-    else
-        iformat = format;
-
-    if (!glamor_pixmap_ensure_fbo(pixmap, iformat, flag))
-        return -1;
-
-    return 0;
-}
-
-/*
- * upload sub region to a large region.
- * */
-static void
-glamor_put_bits(char *dst_bits, int dst_stride, char *src_bits,
-                int src_stride, int bpp, int x, int y, int w, int h)
-{
-    int j;
-    int byte_per_pixel;
-
-    byte_per_pixel = bpp / 8;
-    src_bits += y * src_stride + (x * byte_per_pixel);
-
-    for (j = y; j < y + h; j++) {
-        memcpy(dst_bits, src_bits, w * byte_per_pixel);
-        src_bits += src_stride;
-        dst_bits += dst_stride;
-    }
-}
-
-static Bool
-glamor_upload_sub_pixmap_to_texture(PixmapPtr pixmap, int x, int y, int w,
-                                    int h, int stride, void *bits, int pbo)
-{
-    ScreenPtr screen = pixmap->drawable.pScreen;
-    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
-    GLenum format, type;
-    int no_alpha, revert, swap_rb;
-    glamor_pixmap_private *pixmap_priv;
-    Bool force_clip;
-
-    if (glamor_get_tex_format_type_from_pixmap(pixmap,
-                                               &format,
-                                               &type,
-                                               &no_alpha,
-                                               &revert, &swap_rb, 1)) {
-        glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
-        return FALSE;
-    }
-    if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb))
-        return FALSE;
-
-    pixmap_priv = glamor_get_pixmap_private(pixmap);
-    force_clip = glamor_priv->gl_flavor != GLAMOR_GL_DESKTOP
-        && !glamor_check_fbo_size(glamor_priv, w, h);
-
-    if (glamor_pixmap_priv_is_large(pixmap_priv) || force_clip) {
-        RegionRec region;
-        BoxRec box;
-        int n_region;
-        glamor_pixmap_clipped_regions *clipped_regions;
-        void *sub_bits;
-        int i, j;
-
-        sub_bits = xallocarray(h, stride);
-        if (sub_bits == NULL)
-            return FALSE;
-        box.x1 = x;
-        box.y1 = y;
-        box.x2 = x + w;
-        box.y2 = y + h;
-        RegionInitBoxes(&region, &box, 1);
-        if (!force_clip)
-            clipped_regions =
-                glamor_compute_clipped_regions(pixmap, &region, &n_region,
-                                               0, 0, 0);
-        else
-            clipped_regions =
-                glamor_compute_clipped_regions_ext(pixmap, &region,
-                                                   &n_region,
-                                                   pixmap_priv->block_w,
-                                                   pixmap_priv->block_h,
-                                                   0,
-                                                   0);
-        DEBUGF("prepare upload %dx%d to a large pixmap %p\n", w, h, pixmap);
-        for (i = 0; i < n_region; i++) {
-            BoxPtr boxes;
-            int nbox;
-            int temp_stride;
-            void *temp_bits;
-
-            assert(pbo == 0);
-
-            glamor_set_pixmap_fbo_current(pixmap_priv, clipped_regions[i].block_idx);
-
-            boxes = RegionRects(clipped_regions[i].region);
-            nbox = RegionNumRects(clipped_regions[i].region);
-            DEBUGF("split to %d boxes\n", nbox);
-            for (j = 0; j < nbox; j++) {
-                temp_stride = PixmapBytePad(boxes[j].x2 - boxes[j].x1,
-                                            pixmap->drawable.depth);
-
-                if (boxes[j].x1 == x && temp_stride == stride) {
-                    temp_bits = (char *) bits + (boxes[j].y1 - y) * stride;
-                }
-                else {
-                    temp_bits = sub_bits;
-                    glamor_put_bits(temp_bits, temp_stride, bits, stride,
-                                    pixmap->drawable.bitsPerPixel,
-                                    boxes[j].x1 - x, boxes[j].y1 - y,
-                                    boxes[j].x2 - boxes[j].x1,
-                                    boxes[j].y2 - boxes[j].y1);
-                }
-                DEBUGF("upload x %d y %d w %d h %d temp stride %d \n",
-                       boxes[j].x1 - x, boxes[j].y1 - y,
-                       boxes[j].x2 - boxes[j].x1,
-                       boxes[j].y2 - boxes[j].y1, temp_stride);
-                if (_glamor_upload_bits_to_pixmap_texture
-                    (pixmap, format, type, no_alpha, revert, swap_rb,
-                     boxes[j].x1, boxes[j].y1, boxes[j].x2 - boxes[j].x1,
-                     boxes[j].y2 - boxes[j].y1, temp_stride, temp_bits,
-                     pbo) == FALSE) {
-                    RegionUninit(&region);
-                    free(sub_bits);
-                    assert(0);
-                    return FALSE;
-                }
-            }
-            RegionDestroy(clipped_regions[i].region);
-        }
-        free(sub_bits);
-        free(clipped_regions);
-        RegionUninit(&region);
-        return TRUE;
-    }
-    else
-        return _glamor_upload_bits_to_pixmap_texture(pixmap, format, type,
-                                                     no_alpha, revert, swap_rb,
-                                                     x, y, w, h, stride, bits,
-                                                     pbo);
-}
-
-enum glamor_pixmap_status
-glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
-{
-    int ret;
-
-    if (glamor_upload_sub_pixmap_to_texture(pixmap, 0, 0,
-                                            pixmap->drawable.width,
-                                            pixmap->drawable.height,
-                                            pixmap->devKind,
-                                            pixmap->devPrivate.ptr, 0))
-        ret = GLAMOR_UPLOAD_DONE;
-    else
-        ret = GLAMOR_UPLOAD_FAILED;
-
-    return ret;
-}
diff --git a/glamor/glamor_priv.h b/glamor/glamor_priv.h
index 508433a..2792afa 100644
--- a/glamor/glamor_priv.h
+++ b/glamor/glamor_priv.h
@@ -701,13 +701,6 @@ glamor_put_vbo_space(ScreenPtr screen);
  */
 Bool glamor_pixmap_ensure_fbo(PixmapPtr pixmap, GLenum format, int flag);
 
-/**
- * Upload a pixmap to gl texture. Used by dynamic pixmap
- * uploading feature. The pixmap must be a software pixmap.
- * This function will change current FBO and current shaders.
- */
-enum glamor_pixmap_status glamor_upload_pixmap_to_texture(PixmapPtr pixmap);
-
 glamor_pixmap_clipped_regions *
 glamor_compute_clipped_regions(PixmapPtr pixmap,
                                RegionPtr region, int *clipped_nbox,
-- 
2.1.4



More information about the xorg-devel mailing list