[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(®ion, &box, 1);
+ if (!force_clip)
+ clipped_regions =
+ glamor_compute_clipped_regions(pixmap, ®ion, &n_region,
+ 0, 0, 0);
+ else
+ clipped_regions =
+ glamor_compute_clipped_regions_ext(pixmap, ®ion,
+ &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(®ion);
+ free(sub_bits);
+ assert(0);
+ return FALSE;
+ }
+ }
+ RegionDestroy(clipped_regions[i].region);
+ }
+ free(sub_bits);
+ free(clipped_regions);
+ RegionUninit(®ion);
+ 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(®ion, &box, 1);
- if (!force_clip)
- clipped_regions =
- glamor_compute_clipped_regions(pixmap, ®ion, &n_region,
- 0, 0, 0);
- else
- clipped_regions =
- glamor_compute_clipped_regions_ext(pixmap, ®ion,
- &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(®ion);
- free(sub_bits);
- assert(0);
- return FALSE;
- }
- }
- RegionDestroy(clipped_regions[i].region);
- }
- free(sub_bits);
- free(clipped_regions);
- RegionUninit(®ion);
- 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