From 1fd11c46aa086e4b80cb1bafa87c6b19a8014fd1 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 2 Jul 2015 12:49:36 -0700 Subject: [PATCH] glamor: Move glamor_render.c pict handling to glamor_picture.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Michel Dänzer Reviewed-by: Dave Airlie --- 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 20b9de29f..3b0b7c945 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 5a09d32dd..166bde509 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 508433a45..2792afa3c 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,