gles2: Fixed color conversion for the formats except 1555 and 2101010.

This patch fixed two major problems when we do the color convesion with
GLES2.

1. lack of necessary formats in FBO pool.
GLES2 has three different possible texture formats, GL_RGBA,
GL_BGRA and GL_ALPHA. Previous implementation only has one bucket
for all the three formats which may reuse a incorrect texture format
when do the cache lookup. After this fix, we can enable fbo safely
when running with GLES2.

2. Refine the format matching method in
glamor_get_tex_format_type_from_pictformat.
If both revertion and swap_rb are needed, for example use GL_RGBA
to represent PICT_b8g8r8a8. Then the downloading and uploading should
be handled differently.

    The picture's format is PICT_b8g8r8a8,
    Then the expecting color layout is as below (little endian):
    0   1       2       3   : address
    a   r       g       b

    Now the in GLES2 the supported color format is GL_RGBA, type is
    GL_UNSIGNED_TYPE, then we need to shuffle the fragment
    color as :
        frag_color = sample(texture).argb;
    before we use glReadPixel to get it back.

    For the uploading process, the shuffle is a revert shuffle.
    We still use GL_RGBA, GL_UNSIGNED_BYTE to upload the color
    to a texture, then let's see
    0   1       2       3   : address
    a   r       g       b   : correct colors
    R   G       B       A   : GL_RGBA with GL_UNSIGNED_BYTE

    Now we need to shuffle again, the mapping rule is
    r = G, g = B, b = A, a = R. Then the uploading shuffle is as
    below:
        frag_color = sample(texture).gbar;

After this commit, gles2 version can pass render check with all
the formats except those 1555/2101010.

Signed-off-by: Zhigang Gong <zhigang.gong@linux.intel.com>
This commit is contained in:
Zhigang Gong 2012-04-05 21:53:44 +08:00 committed by Eric Anholt
parent 55fdc7b196
commit 3add375065
11 changed files with 365 additions and 223 deletions

View File

@ -84,6 +84,7 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
glamor_pixmap_private *pixmap_priv; glamor_pixmap_private *pixmap_priv;
glamor_screen_private *glamor_priv; glamor_screen_private *glamor_priv;
glamor_pixmap_fbo *fbo; glamor_pixmap_fbo *fbo;
GLenum format;
glamor_priv = glamor_get_screen_private(screen); glamor_priv = glamor_get_screen_private(screen);
pixmap_priv = glamor_get_pixmap_private(pixmap); pixmap_priv = glamor_get_pixmap_private(pixmap);
@ -93,9 +94,10 @@ glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex)
glamor_destroy_fbo(fbo); glamor_destroy_fbo(fbo);
} }
gl_iformat_for_depth(pixmap->drawable.depth, &format);
fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap->drawable.width, fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap->drawable.width,
pixmap->drawable.height, pixmap->drawable.height,
pixmap->drawable.depth, tex, 0); format, tex, 0);
if (fbo == NULL) { if (fbo == NULL) {
ErrorF("XXX fail to create fbo.\n"); ErrorF("XXX fail to create fbo.\n");
@ -133,11 +135,14 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
glamor_pixmap_fbo *fbo; glamor_pixmap_fbo *fbo;
int pitch; int pitch;
int flag; int flag;
GLenum format;
if (w > 32767 || h > 32767) if (w > 32767 || h > 32767)
return NullPixmap; return NullPixmap;
if (usage == GLAMOR_CREATE_PIXMAP_CPU || (w == 0 && h == 0)) if (usage == GLAMOR_CREATE_PIXMAP_CPU
|| (w == 0 && h == 0)
|| !glamor_check_pixmap_fbo_depth(depth))
return fbCreatePixmap(screen, w, h, depth, usage); return fbCreatePixmap(screen, w, h, depth, usage);
else else
pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
@ -154,7 +159,8 @@ glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
pixmap_priv->glamor_priv = glamor_priv; pixmap_priv->glamor_priv = glamor_priv;
pixmap_priv->type = type; pixmap_priv->type = type;
fbo = glamor_create_fbo(glamor_priv, w, h, depth, usage); gl_iformat_for_depth(depth, &format);
fbo = glamor_create_fbo(glamor_priv, w, h, format, usage);
if (fbo == NULL) { if (fbo == NULL) {
fbDestroyPixmap(pixmap); fbDestroyPixmap(pixmap);

View File

@ -239,12 +239,10 @@ glamor_copy_n_to_n_textured(DrawablePtr src,
texcoords); texcoords);
dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); dispatch->glUseProgram(glamor_priv->finish_access_prog[0]);
dispatch-> dispatch->glUniform1i(glamor_priv->finish_access_revert[0],
glUniform1i(glamor_priv->finish_access_no_revert[0], REVERT_NONE);
1); dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0],
dispatch-> SWAP_NONE_UPLOADING);
glUniform1i(glamor_priv->finish_access_swap_rb[0], 0);
} else { } else {
GLAMOR_CHECK_PENDING_FILL(dispatch, glamor_priv, GLAMOR_CHECK_PENDING_FILL(dispatch, glamor_priv,
src_pixmap_priv); src_pixmap_priv);

View File

@ -107,6 +107,35 @@ glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
return glamor_download_pixmap_to_cpu(pixmap, access); return glamor_download_pixmap_to_cpu(pixmap, access);
} }
/*
* When downloading a unsupported color format to CPU memory,
we need to shuffle the color elements and then use a supported
color format to read it back to CPU memory.
For an example, the picture's format is PICT_b8g8r8a8,
Then the expecting color layout is as below (little endian):
0 1 2 3 : address
a r g b
Now the in GLES2 the supported color format is GL_RGBA, type is
GL_UNSIGNED_TYPE, then we need to shuffle the fragment
color as :
frag_color = sample(texture).argb;
before we use glReadPixel to get it back.
For the uploading process, the shuffle is a revert shuffle.
We still use GL_RGBA, GL_UNSIGNED_BYTE to upload the color
to a texture, then let's see
0 1 2 3 : address
a r g b : correct colors
R G B A : GL_RGBA with GL_UNSIGNED_BYTE
Now we need to shuffle again, the mapping rule is
r = G, g = B, b = A, a = R. Then the uploading shuffle is as
below:
frag_color = sample(texture).gbar;
*/
void void
glamor_init_finish_access_shaders(ScreenPtr screen) glamor_init_finish_access_shaders(ScreenPtr screen)
{ {
@ -121,53 +150,67 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
" gl_Position = v_position;\n" " gl_Position = v_position;\n"
" source_texture = v_texcoord0.xy;\n" "}\n"; " source_texture = v_texcoord0.xy;\n" "}\n";
const char *fs_source = const char *common_source =
GLAMOR_DEFAULT_PRECISION GLAMOR_DEFAULT_PRECISION
"varying vec2 source_texture;\n" "varying vec2 source_texture;\n"
"uniform sampler2D sampler;\n" "uniform sampler2D sampler;\n"
"uniform int no_revert;\n" "uniform int revert;\n"
"uniform int swap_rb;\n" "uniform int swap_rb;\n"
"#define REVERT_NONE 0\n"
"#define REVERT_NORMAL 1\n"
"#define SWAP_NONE_DOWNLOADING 0\n"
"#define SWAP_DOWNLOADING 1\n"
"#define SWAP_UPLOADING 2\n"
"#define SWAP_NONE_UPLOADING 3\n";
const char *fs_source =
"void main()\n" "void main()\n"
"{\n" "{\n"
" if (no_revert == 1) \n" " if (revert == REVERT_NONE) \n"
" { \n" " { \n"
" if (swap_rb == 1) \n" " if ((swap_rb != SWAP_NONE_DOWNLOADING) && (swap_rb != SWAP_NONE_UPLOADING)) \n"
" gl_FragColor = texture2D(sampler, source_texture).bgra;\n" " gl_FragColor = texture2D(sampler, source_texture).bgra;\n"
" else \n" " else \n"
" gl_FragColor = texture2D(sampler, source_texture).rgba;\n" " gl_FragColor = texture2D(sampler, source_texture).rgba;\n"
" } \n" " } \n"
" else \n" " else \n"
" { \n" " { \n"
" if (swap_rb == 1) \n" " if (swap_rb == SWAP_DOWNLOADING) \n"
" gl_FragColor = texture2D(sampler, source_texture).argb;\n" " gl_FragColor = texture2D(sampler, source_texture).argb;\n"
" else \n" " else if (swap_rb == SWAP_NONE_DOWNLOADING)\n"
" gl_FragColor = texture2D(sampler, source_texture).abgr;\n" " gl_FragColor = texture2D(sampler, source_texture).abgr;\n"
" else if (swap_rb == SWAP_UPLOADING)\n"
" gl_FragColor = texture2D(sampler, source_texture).gbar;\n"
" else if (swap_rb == SWAP_NONE_UPLOADING)\n"
" gl_FragColor = texture2D(sampler, source_texture).abgr;\n"
" } \n" "}\n"; " } \n" "}\n";
const char *set_alpha_source = const char *set_alpha_source =
GLAMOR_DEFAULT_PRECISION
"varying vec2 source_texture;\n"
"uniform sampler2D sampler;\n"
"uniform int no_revert;\n"
"uniform int swap_rb;\n"
"void main()\n" "void main()\n"
"{\n" "{\n"
" if (no_revert == 1) \n" " if (revert == REVERT_NONE) \n"
" { \n" " { \n"
" if (swap_rb == 1) \n" " if ((swap_rb != SWAP_NONE_DOWNLOADING) && (swap_rb != SWAP_NONE_UPLOADING)) \n"
" gl_FragColor = vec4(texture2D(sampler, source_texture).bgr, 1);\n" " gl_FragColor = vec4(texture2D(sampler, source_texture).bgr, 1);\n"
" else \n" " else \n"
" gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n" " gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n"
" } \n" " } \n"
" else \n" " else \n"
" { \n" " { \n"
" if (swap_rb == 1) \n" " if (swap_rb == SWAP_DOWNLOADING) \n"
" gl_FragColor = vec4(1, texture2D(sampler, source_texture).rgb);\n" " gl_FragColor = vec4(1, texture2D(sampler, source_texture).rgb);\n"
" else \n" " else if (swap_rb == SWAP_NONE_DOWNLOADING)\n"
" gl_FragColor = vec4(1, texture2D(sampler, source_texture).bgr);\n" " gl_FragColor = vec4(1, texture2D(sampler, source_texture).bgr);\n"
" } \n" "}\n"; " else if (swap_rb == SWAP_UPLOADING)\n"
" gl_FragColor = vec4(texture2D(sampler, source_texture).gba, 1);\n"
" else if (swap_rb == SWAP_NONE_UPLOADING)\n"
" gl_FragColor = vec4(texture2D(sampler, source_texture).abg, 1);\n"
" } \n"
"}\n";
GLint fs_prog, vs_prog, avs_prog, set_alpha_prog; GLint fs_prog, vs_prog, avs_prog, set_alpha_prog;
GLint sampler_uniform_location; GLint sampler_uniform_location;
char *source;
glamor_priv = glamor_get_screen_private(screen); glamor_priv = glamor_get_screen_private(screen);
dispatch = glamor_get_dispatch(glamor_priv); dispatch = glamor_get_dispatch(glamor_priv);
@ -176,8 +219,12 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, vs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER,
vs_source); vs_source);
XNFasprintf(&source, "%s%s", common_source, fs_source);
fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, fs_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER,
fs_source); source);
free(source);
dispatch->glAttachShader(glamor_priv->finish_access_prog[0], dispatch->glAttachShader(glamor_priv->finish_access_prog[0],
vs_prog); vs_prog);
dispatch->glAttachShader(glamor_priv->finish_access_prog[0], dispatch->glAttachShader(glamor_priv->finish_access_prog[0],
@ -185,8 +232,12 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
avs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER, avs_prog = glamor_compile_glsl_prog(dispatch, GL_VERTEX_SHADER,
vs_source); vs_source);
XNFasprintf(&source, "%s%s", common_source, set_alpha_source);
set_alpha_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER, set_alpha_prog = glamor_compile_glsl_prog(dispatch, GL_FRAGMENT_SHADER,
set_alpha_source); source);
free(source);
dispatch->glAttachShader(glamor_priv->finish_access_prog[1], dispatch->glAttachShader(glamor_priv->finish_access_prog[1],
avs_prog); avs_prog);
dispatch->glAttachShader(glamor_priv->finish_access_prog[1], dispatch->glAttachShader(glamor_priv->finish_access_prog[1],
@ -208,10 +259,10 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
glamor_link_glsl_prog(dispatch, glamor_link_glsl_prog(dispatch,
glamor_priv->finish_access_prog[1]); glamor_priv->finish_access_prog[1]);
glamor_priv->finish_access_no_revert[0] = glamor_priv->finish_access_revert[0] =
dispatch-> dispatch->
glGetUniformLocation(glamor_priv->finish_access_prog[0], glGetUniformLocation(glamor_priv->finish_access_prog[0],
"no_revert"); "revert");
glamor_priv->finish_access_swap_rb[0] = glamor_priv->finish_access_swap_rb[0] =
dispatch-> dispatch->
@ -223,14 +274,14 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
"sampler"); "sampler");
dispatch->glUseProgram(glamor_priv->finish_access_prog[0]); dispatch->glUseProgram(glamor_priv->finish_access_prog[0]);
dispatch->glUniform1i(sampler_uniform_location, 0); dispatch->glUniform1i(sampler_uniform_location, 0);
dispatch->glUniform1i(glamor_priv->finish_access_no_revert[0], 1); dispatch->glUniform1i(glamor_priv->finish_access_revert[0], 0);
dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], 0); dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[0], 0);
dispatch->glUseProgram(0); dispatch->glUseProgram(0);
glamor_priv->finish_access_no_revert[1] = glamor_priv->finish_access_revert[1] =
dispatch-> dispatch->
glGetUniformLocation(glamor_priv->finish_access_prog[1], glGetUniformLocation(glamor_priv->finish_access_prog[1],
"no_revert"); "revert");
glamor_priv->finish_access_swap_rb[1] = glamor_priv->finish_access_swap_rb[1] =
dispatch-> dispatch->
glGetUniformLocation(glamor_priv->finish_access_prog[1], glGetUniformLocation(glamor_priv->finish_access_prog[1],
@ -240,7 +291,7 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
glGetUniformLocation(glamor_priv->finish_access_prog[1], glGetUniformLocation(glamor_priv->finish_access_prog[1],
"sampler"); "sampler");
dispatch->glUseProgram(glamor_priv->finish_access_prog[1]); dispatch->glUseProgram(glamor_priv->finish_access_prog[1]);
dispatch->glUniform1i(glamor_priv->finish_access_no_revert[1], 1); dispatch->glUniform1i(glamor_priv->finish_access_revert[1], 0);
dispatch->glUniform1i(sampler_uniform_location, 0); dispatch->glUniform1i(sampler_uniform_location, 0);
dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[1], 0); dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[1], 0);
dispatch->glUseProgram(0); dispatch->glUseProgram(0);

View File

@ -62,18 +62,6 @@ inline static int cache_hbucket(int size)
order = CACHE_BUCKET_HCOUNT - 1; order = CACHE_BUCKET_HCOUNT - 1;
return order; return order;
} }
inline static int cache_format(GLenum format)
{
switch (format) {
#if 0
case GL_ALPHA:
return 1;
#endif
case GL_RGBA:
default:
return 0;
}
}
glamor_pixmap_fbo * glamor_pixmap_fbo *
glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv, glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv,
@ -82,23 +70,27 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv,
struct xorg_list *cache; struct xorg_list *cache;
glamor_pixmap_fbo *fbo_entry; glamor_pixmap_fbo *fbo_entry;
int size; int size;
int n_format;
#ifdef NO_FBO_CACHE #ifdef NO_FBO_CACHE
return NULL; return NULL;
#else #else
n_format = cache_format(format);
if (n_format == -1)
return NULL;
if (!(flag & GLAMOR_CACHE_TEXTURE)) if (!(flag & GLAMOR_CACHE_TEXTURE))
cache = &glamor_priv->fbo_cache[cache_format(format)] cache = &glamor_priv->fbo_cache[n_format]
[cache_wbucket(w)] [cache_wbucket(w)]
[cache_hbucket(h)]; [cache_hbucket(h)];
else else
cache = &glamor_priv->tex_cache[cache_format(format)] cache = &glamor_priv->tex_cache[n_format]
[cache_wbucket(w)] [cache_wbucket(w)]
[cache_hbucket(h)]; [cache_hbucket(h)];
if (!(flag & GLAMOR_CACHE_EXACT_SIZE)) { if (!(flag & GLAMOR_CACHE_EXACT_SIZE)) {
xorg_list_for_each_entry(fbo_entry, cache, list) { xorg_list_for_each_entry(fbo_entry, cache, list) {
if (fbo_entry->width >= w && fbo_entry->height >= h) { if (fbo_entry->width >= w && fbo_entry->height >= h) {
DEBUGF("Request w %d h %d \n", w, h); DEBUGF("Request w %d h %d format %x \n", w, h, format);
DEBUGF("got cache entry %p w %d h %d fbo %d tex %d\n", DEBUGF("got cache entry %p w %d h %d fbo %d tex %d format %x\n",
fbo_entry, fbo_entry->width, fbo_entry->height, fbo_entry, fbo_entry->width, fbo_entry->height,
fbo_entry->fb, fbo_entry->tex); fbo_entry->fb, fbo_entry->tex);
xorg_list_del(&fbo_entry->list); xorg_list_del(&fbo_entry->list);
@ -110,10 +102,11 @@ glamor_pixmap_fbo_cache_get(glamor_screen_private *glamor_priv,
xorg_list_for_each_entry(fbo_entry, cache, list) { xorg_list_for_each_entry(fbo_entry, cache, list) {
if (fbo_entry->width == w && fbo_entry->height == h) { if (fbo_entry->width == w && fbo_entry->height == h) {
DEBUGF("Request w %d h %d \n", w, h); DEBUGF("Request w %d h %d format %x \n", w, h, format);
DEBUGF("got cache entry %p w %d h %d fbo %d tex %d\n", DEBUGF("got cache entry %p w %d h %d fbo %d tex %d format %x\n",
fbo_entry, fbo_entry->width, fbo_entry->height, fbo_entry, fbo_entry->width, fbo_entry->height,
fbo_entry->fb, fbo_entry->tex); fbo_entry->fb, fbo_entry->tex, fbo_entry->format);
assert(format == fbo_entry->format);
xorg_list_del(&fbo_entry->list); xorg_list_del(&fbo_entry->list);
return fbo_entry; return fbo_entry;
} }
@ -144,21 +137,25 @@ static void
glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo) glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo)
{ {
struct xorg_list *cache; struct xorg_list *cache;
int n_format;
#ifdef NO_FBO_CACHE #ifdef NO_FBO_CACHE
glamor_purge_fbo(fbo); glamor_purge_fbo(fbo);
return; return;
#else #else
if (fbo->fb == 0) { n_format = cache_format(fbo->format);
if (fbo->fb == 0 || n_format == -1) {
glamor_purge_fbo(fbo); glamor_purge_fbo(fbo);
return; return;
} }
if (fbo->fb) if (fbo->fb)
cache = &fbo->glamor_priv->fbo_cache[cache_format(fbo->format)] cache = &fbo->glamor_priv->fbo_cache[n_format]
[cache_wbucket(fbo->width)] [cache_wbucket(fbo->width)]
[cache_hbucket(fbo->height)]; [cache_hbucket(fbo->height)];
else else
cache = &fbo->glamor_priv->tex_cache[cache_format(fbo->format)] cache = &fbo->glamor_priv->tex_cache[n_format]
[cache_wbucket(fbo->width)] [cache_wbucket(fbo->width)]
[cache_hbucket(fbo->height)]; [cache_hbucket(fbo->height)];
DEBUGF("Put cache entry %p to cache %p w %d h %d format %x fbo %d tex %d \n", fbo, cache, DEBUGF("Put cache entry %p to cache %p w %d h %d format %x fbo %d tex %d \n", fbo, cache,
@ -170,17 +167,15 @@ glamor_pixmap_fbo_cache_put(glamor_pixmap_fbo *fbo)
glamor_pixmap_fbo * glamor_pixmap_fbo *
glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
int w, int h, int depth, GLint tex, int flag) int w, int h, GLenum format, GLint tex, int flag)
{ {
glamor_pixmap_fbo *fbo; glamor_pixmap_fbo *fbo;
GLenum format;
fbo = calloc(1, sizeof(*fbo)); fbo = calloc(1, sizeof(*fbo));
if (fbo == NULL) if (fbo == NULL)
return NULL; return NULL;
xorg_list_init(&fbo->list); xorg_list_init(&fbo->list);
gl_iformat_for_depth(depth, &format);
fbo->tex = tex; fbo->tex = tex;
fbo->width = w; fbo->width = w;
@ -338,19 +333,18 @@ glamor_destroy_tex_obj(glamor_pixmap_fbo * tex_obj)
glamor_pixmap_fbo * glamor_pixmap_fbo *
glamor_create_fbo(glamor_screen_private *glamor_priv, glamor_create_fbo(glamor_screen_private *glamor_priv,
int w, int h, int depth, int flag) int w, int h,
GLenum format,
int flag)
{ {
glamor_gl_dispatch *dispatch; glamor_gl_dispatch *dispatch;
glamor_pixmap_fbo *fbo; glamor_pixmap_fbo *fbo;
GLenum format;
GLint tex; GLint tex;
int cache_flag; int cache_flag;
if (!glamor_check_fbo_size(glamor_priv, w, h) if (!glamor_check_fbo_size(glamor_priv, w, h))
|| !glamor_check_fbo_depth(depth))
return NULL; return NULL;
gl_iformat_for_depth(depth, &format);
if (flag == GLAMOR_CREATE_FBO_NO_FBO) if (flag == GLAMOR_CREATE_FBO_NO_FBO)
goto new_fbo; goto new_fbo;
@ -374,7 +368,7 @@ new_fbo:
dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, dispatch->glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format,
GL_UNSIGNED_BYTE, NULL); GL_UNSIGNED_BYTE, NULL);
fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, depth, tex, flag); fbo = glamor_create_fbo_from_tex(glamor_priv, w, h, format, tex, flag);
glamor_put_dispatch(glamor_priv); glamor_put_dispatch(glamor_priv);
return fbo; return fbo;

View File

@ -39,10 +39,11 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h,
struct glamor_screen_private *glamor_priv; struct glamor_screen_private *glamor_priv;
int x_off, y_off; int x_off, y_off;
GLenum tex_format, tex_type; GLenum tex_format, tex_type;
int no_alpha, no_revert; int no_alpha, revert;
PixmapPtr temp_pixmap = NULL; glamor_pixmap_fbo *temp_fbo = NULL;
glamor_gl_dispatch * dispatch; glamor_gl_dispatch * dispatch;
Bool ret = FALSE; Bool ret = FALSE;
int swap_rb;
goto fall_back; goto fall_back;
@ -69,7 +70,9 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h,
&tex_format, &tex_format,
&tex_type, &tex_type,
&no_alpha, &no_alpha,
&no_revert)) { &revert,
&swap_rb,
0)) {
glamor_fallback("unknown depth. %d \n", drawable->depth); glamor_fallback("unknown depth. %d \n", drawable->depth);
goto fall_back; goto fall_back;
} }
@ -78,14 +81,16 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h,
glamor_validate_pixmap(pixmap); glamor_validate_pixmap(pixmap);
if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
&& (glamor_tex_format_is_readable(format) || !no_revert)) { && ( swap_rb != SWAP_NONE_DOWNLOADING
|| revert != REVERT_NONE)) {
/* XXX prepare whole pixmap is not efficient. */ /* XXX prepare whole pixmap is not efficient. */
temp_pixmap = temp_fbo =
glamor_es2_pixmap_read_prepare(pixmap, &tex_format, glamor_es2_pixmap_read_prepare(pixmap, tex_format,
&tex_type, no_alpha, tex_type, no_alpha,
no_revert); revert, swap_rb);
pixmap_priv = glamor_get_pixmap_private(temp_pixmap); if (temp_fbo == NULL)
glamor_set_destination_pixmap_priv_nc(pixmap_priv); goto fall_back;
} }
int row_length = PixmapBytePad(w, drawable->depth); int row_length = PixmapBytePad(w, drawable->depth);
@ -113,8 +118,8 @@ _glamor_get_image(DrawablePtr drawable, int x, int y, int w, int h,
tex_format, tex_format,
tex_type, d); tex_type, d);
glamor_put_dispatch(glamor_priv); glamor_put_dispatch(glamor_priv);
if (temp_pixmap) if (temp_fbo)
glamor_destroy_pixmap(temp_pixmap); glamor_destroy_fbo(temp_fbo);
ret = TRUE; ret = TRUE;

View File

@ -35,17 +35,18 @@ _glamor_get_spans(DrawablePtr drawable,
{ {
PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable); PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
GLenum format, type; GLenum format, type;
int no_alpha, no_revert; int no_alpha, revert;
glamor_screen_private *glamor_priv = glamor_screen_private *glamor_priv =
glamor_get_screen_private(drawable->pScreen); glamor_get_screen_private(drawable->pScreen);
glamor_pixmap_private *pixmap_priv = glamor_pixmap_private *pixmap_priv =
glamor_get_pixmap_private(pixmap); glamor_get_pixmap_private(pixmap);
glamor_gl_dispatch *dispatch; glamor_gl_dispatch *dispatch;
PixmapPtr temp_pixmap = NULL; glamor_pixmap_fbo *temp_fbo = NULL;
int i; int i;
uint8_t *readpixels_dst = (uint8_t *) dst; uint8_t *readpixels_dst = (uint8_t *) dst;
int x_off, y_off; int x_off, y_off;
Bool ret = FALSE; Bool ret = FALSE;
int swap_rb;
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) { if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) {
glamor_fallback("pixmap has no fbo.\n"); glamor_fallback("pixmap has no fbo.\n");
@ -55,24 +56,29 @@ _glamor_get_spans(DrawablePtr drawable,
if (glamor_get_tex_format_type_from_pixmap(pixmap, if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format, &format,
&type, &no_alpha, &type, &no_alpha,
&no_revert)) { &revert, &swap_rb, 0)) {
glamor_fallback("unknown depth. %d \n", drawable->depth); glamor_fallback("unknown depth. %d \n", drawable->depth);
goto fail; goto fail;
} }
if (revert > REVERT_NORMAL)
goto fail;
glamor_set_destination_pixmap_priv_nc(pixmap_priv); glamor_set_destination_pixmap_priv_nc(pixmap_priv);
glamor_validate_pixmap(pixmap); glamor_validate_pixmap(pixmap);
if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
&& (!glamor_tex_format_is_readable(format) || !no_revert)) { && ( swap_rb != SWAP_NONE_DOWNLOADING
|| revert != REVERT_NONE)) {
/* XXX prepare whole pixmap is not efficient. */ /* XXX prepare whole pixmap is not efficient. */
temp_pixmap = temp_fbo =
glamor_es2_pixmap_read_prepare(pixmap, &format, glamor_es2_pixmap_read_prepare(pixmap, format,
&type, no_alpha, type, no_alpha,
no_revert); revert, swap_rb);
pixmap_priv = glamor_get_pixmap_private(temp_pixmap); if (temp_fbo == NULL)
glamor_set_destination_pixmap_priv_nc(pixmap_priv); goto fail;
} }
glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off); glamor_get_drawable_deltas(drawable, pixmap, &x_off, &y_off);
@ -94,8 +100,8 @@ _glamor_get_spans(DrawablePtr drawable,
PixmapBytePad(widths[i], drawable->depth); PixmapBytePad(widths[i], drawable->depth);
} }
glamor_put_dispatch(glamor_priv); glamor_put_dispatch(glamor_priv);
if (temp_pixmap) if (temp_fbo)
glamor_destroy_pixmap(temp_pixmap); glamor_destroy_fbo(temp_fbo);
ret = TRUE; ret = TRUE;
goto done; goto done;
@ -105,6 +111,7 @@ fail:
&& glamor_ddx_fallback_check_pixmap(drawable)) && glamor_ddx_fallback_check_pixmap(drawable))
goto done; goto done;
ret = TRUE;
glamor_fallback("from %p (%c)\n", drawable, glamor_fallback("from %p (%c)\n", drawable,
glamor_get_drawable_location(drawable)); glamor_get_drawable_location(drawable));
if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) { if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RO)) {

View File

@ -89,10 +89,10 @@ glamor_validate_pixmap(PixmapPtr pixmap)
} }
void void
glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv) glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo * fbo)
{ {
glamor_gl_dispatch *dispatch = glamor_get_dispatch(pixmap_priv->glamor_priv); glamor_gl_dispatch *dispatch = glamor_get_dispatch(fbo->glamor_priv);
dispatch->glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fbo->fb); dispatch->glBindFramebuffer(GL_FRAMEBUFFER, fbo->fb);
#ifndef GLAMOR_GLES2 #ifndef GLAMOR_GLES2
dispatch->glMatrixMode(GL_PROJECTION); dispatch->glMatrixMode(GL_PROJECTION);
dispatch->glLoadIdentity(); dispatch->glLoadIdentity();
@ -100,10 +100,16 @@ glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv)
dispatch->glLoadIdentity(); dispatch->glLoadIdentity();
#endif #endif
dispatch->glViewport(0, 0, dispatch->glViewport(0, 0,
pixmap_priv->fbo->width, fbo->width,
pixmap_priv->fbo->height); fbo->height);
glamor_put_dispatch(pixmap_priv->glamor_priv); glamor_put_dispatch(fbo->glamor_priv);
}
void
glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * pixmap_priv)
{
glamor_set_destination_pixmap_fbo(pixmap_priv->fbo);
} }
int int
@ -280,9 +286,8 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
* */ * */
static void static void
_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type,
GLenum type, int no_alpha, int no_revert, int no_alpha, int revert, int swap_rb)
int flip)
{ {
glamor_pixmap_private *pixmap_priv = glamor_pixmap_private *pixmap_priv =
@ -308,7 +313,7 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
if (!pixmap_priv) if (!pixmap_priv)
return; return;
need_flip = (flip && !glamor_priv->yInverted); need_flip = !glamor_priv->yInverted;
glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DYNAMIC_UPLOAD, glamor_debug_output(GLAMOR_DEBUG_TEXTURE_DYNAMIC_UPLOAD,
"Uploading pixmap %p %dx%d depth%d.\n", "Uploading pixmap %p %dx%d depth%d.\n",
@ -319,7 +324,11 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
/* Try fast path firstly, upload the pixmap to the texture attached /* Try fast path firstly, upload the pixmap to the texture attached
* to the fbo directly. */ * to the fbo directly. */
if (no_alpha == 0 && no_revert == 1 && !need_flip) { if (no_alpha == 0
&& revert == REVERT_NONE
&& swap_rb == SWAP_NONE_UPLOADING
&& !need_flip) {
__glamor_upload_pixmap_to_texture(pixmap, format, type, __glamor_upload_pixmap_to_texture(pixmap, format, type,
pixmap_priv->fbo->tex, 1); pixmap_priv->fbo->tex, 1);
return; return;
@ -365,10 +374,10 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
#endif #endif
dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
dispatch->glUniform1i(glamor_priv-> dispatch->glUniform1i(glamor_priv->
finish_access_no_revert[no_alpha], finish_access_revert[no_alpha],
no_revert); revert);
dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha],
0); swap_rb);
dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4); dispatch->glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
@ -441,18 +450,22 @@ glamor_pixmap_ensure_fb(glamor_pixmap_fbo *fbo)
* 2. no_alpha != 0, we need to wire the alpha. * 2. no_alpha != 0, we need to wire the alpha.
* */ * */
static int static int
glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert) glamor_pixmap_upload_prepare(PixmapPtr pixmap, GLenum format, int no_alpha, int revert, int swap_rb)
{ {
int flag; int flag;
glamor_pixmap_private *pixmap_priv; glamor_pixmap_private *pixmap_priv;
glamor_screen_private *glamor_priv; glamor_screen_private *glamor_priv;
GLenum format;
glamor_pixmap_fbo *fbo; glamor_pixmap_fbo *fbo;
GLenum iformat;
pixmap_priv = glamor_get_pixmap_private(pixmap); pixmap_priv = glamor_get_pixmap_private(pixmap);
glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen); glamor_priv = glamor_get_screen_private(pixmap->drawable.pScreen);
if (!(no_alpha || !no_revert || !glamor_priv->yInverted)) { if (!(no_alpha
|| (revert != REVERT_NONE)
|| (swap_rb != SWAP_NONE_UPLOADING)
|| !glamor_priv->yInverted)) {
/* We don't need a fbo, a simple texture uploading should work. */
if (pixmap_priv && pixmap_priv->fbo) if (pixmap_priv && pixmap_priv->fbo)
return 0; return 0;
@ -464,9 +477,15 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert)
flag = 0; flag = 0;
} }
if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP)
gl_iformat_for_depth(pixmap->drawable.depth, &iformat);
else
iformat = format;
fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width, fbo = glamor_create_fbo(glamor_priv, pixmap->drawable.width,
pixmap->drawable.height, pixmap->drawable.height,
pixmap->drawable.depth, iformat,
flag); flag);
if (fbo == NULL) { if (fbo == NULL) {
glamor_fallback glamor_fallback
@ -485,20 +504,24 @@ enum glamor_pixmap_status
glamor_upload_pixmap_to_texture(PixmapPtr pixmap) glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
{ {
GLenum format, type; GLenum format, type;
int no_alpha, no_revert; int no_alpha, revert, swap_rb;
if (glamor_get_tex_format_type_from_pixmap(pixmap, if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format, &format,
&type, &no_alpha, &type,
&no_revert)) { &no_alpha,
&revert,
&swap_rb, 1)) {
glamor_fallback("Unknown pixmap depth %d.\n", glamor_fallback("Unknown pixmap depth %d.\n",
pixmap->drawable.depth); pixmap->drawable.depth);
return GLAMOR_UPLOAD_FAILED; return GLAMOR_UPLOAD_FAILED;
} }
if (glamor_pixmap_upload_prepare(pixmap, no_alpha, no_revert))
if (glamor_pixmap_upload_prepare(pixmap, format, no_alpha, revert, swap_rb))
return GLAMOR_UPLOAD_FAILED; return GLAMOR_UPLOAD_FAILED;
_glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha,
no_revert, 1); revert, swap_rb);
return GLAMOR_UPLOAD_DONE; return GLAMOR_UPLOAD_DONE;
} }
@ -523,21 +546,19 @@ void
glamor_restore_pixmap_to_texture(PixmapPtr pixmap) glamor_restore_pixmap_to_texture(PixmapPtr pixmap)
{ {
GLenum format, type; GLenum format, type;
int no_alpha, no_revert; int no_alpha, revert, swap_rb;
if (glamor_get_tex_format_type_from_pixmap(pixmap, if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format, &format,
&type, &no_alpha, &type, &no_alpha,
&no_revert)) { &revert, &swap_rb, 1)) {
ErrorF("Unknown pixmap depth %d.\n", ErrorF("Unknown pixmap depth %d.\n",
pixmap->drawable.depth); pixmap->drawable.depth);
assert(0); assert(0);
} }
in_restore = 1;
_glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha,
no_revert, 1); revert, swap_rb);
in_restore = 0;
} }
/* /*
@ -548,65 +569,56 @@ glamor_restore_pixmap_to_texture(PixmapPtr pixmap)
* get a new temporary pixmap returned. * get a new temporary pixmap returned.
* */ * */
PixmapPtr glamor_pixmap_fbo *
glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format,
GLenum * type, int no_alpha, int no_revert) GLenum type, int no_alpha, int revert, int swap_rb)
{ {
glamor_pixmap_private *source_priv; glamor_pixmap_private *source_priv;
glamor_screen_private *glamor_priv; glamor_screen_private *glamor_priv;
ScreenPtr screen; ScreenPtr screen;
PixmapPtr temp_pixmap; glamor_pixmap_fbo *temp_fbo;
glamor_pixmap_private *temp_pixmap_priv;
glamor_gl_dispatch *dispatch; glamor_gl_dispatch *dispatch;
static float vertices[8] = { -1, -1, float temp_xscale, temp_yscale, source_xscale, source_yscale;
1, -1, static float vertices[8];
1, 1, static float texcoords[8];
-1, 1
};
static float texcoords[8] = { 0, 0,
1, 0,
1, 1,
0, 1
};
int swap_rb = 0;
screen = source->drawable.pScreen; screen = source->drawable.pScreen;
glamor_priv = glamor_get_screen_private(screen); glamor_priv = glamor_get_screen_private(screen);
source_priv = glamor_get_pixmap_private(source); source_priv = glamor_get_pixmap_private(source);
if (*format == GL_BGRA) { temp_fbo = glamor_create_fbo(glamor_priv,
*format = GL_RGBA; source->drawable.width,
swap_rb = 1; source->drawable.height,
} format,
0);
if (temp_fbo == NULL)
temp_pixmap = glamor_create_pixmap (screen, return NULL;
source->drawable.width,
source->drawable.height,
source->drawable.depth, 0);
temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap);
dispatch = glamor_get_dispatch(glamor_priv); dispatch = glamor_get_dispatch(glamor_priv);
dispatch->glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->fbo->tex); temp_xscale = 1.0 / temp_fbo->width;
dispatch->glTexParameteri(GL_TEXTURE_2D, temp_yscale = 1.0 / temp_fbo->height;
GL_TEXTURE_MIN_FILTER,
GL_NEAREST);
dispatch->glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER,
GL_NEAREST);
dispatch->glTexImage2D(GL_TEXTURE_2D, 0, *format, glamor_set_normalize_vcoords(temp_xscale,
source->drawable.width, temp_yscale,
source->drawable.height, 0, *format, *type, 0, 0,
NULL); source->drawable.width, source->drawable.height,
glamor_priv->yInverted,
vertices);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, dispatch->glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT,
GL_FALSE, 2 * sizeof(float), GL_FALSE, 2 * sizeof(float),
vertices); vertices);
dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS); dispatch->glEnableVertexAttribArray(GLAMOR_VERTEX_POS);
pixmap_priv_get_scale(source_priv, &source_xscale, &source_yscale);
glamor_set_normalize_tcoords(source_xscale,
source_yscale,
0, 0,
source->drawable.width, source->drawable.height,
glamor_priv->yInverted,
texcoords);
dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT, dispatch->glVertexAttribPointer(GLAMOR_VERTEX_SOURCE, 2, GL_FLOAT,
GL_FALSE, 2 * sizeof(float), GL_FALSE, 2 * sizeof(float),
texcoords); texcoords);
@ -621,12 +633,11 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format,
GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MAG_FILTER,
GL_NEAREST); GL_NEAREST);
glamor_set_destination_pixmap_priv_nc(temp_pixmap_priv); glamor_set_destination_pixmap_fbo(temp_fbo);
dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
dispatch->glUniform1i(glamor_priv-> dispatch->glUniform1i(glamor_priv->
finish_access_no_revert[no_alpha], finish_access_revert[no_alpha],
no_revert); revert);
dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha],
swap_rb); swap_rb);
@ -636,7 +647,7 @@ glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format,
dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE); dispatch->glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
dispatch->glUseProgram(0); dispatch->glUseProgram(0);
glamor_put_dispatch(glamor_priv); glamor_put_dispatch(glamor_priv);
return temp_pixmap; return temp_fbo;
} }
@ -656,21 +667,23 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
glamor_get_pixmap_private(pixmap); glamor_get_pixmap_private(pixmap);
unsigned int stride, row_length, y; unsigned int stride, row_length, y;
GLenum format, type, gl_access, gl_usage; GLenum format, type, gl_access, gl_usage;
int no_alpha, no_revert; int no_alpha, revert, swap_rb;
uint8_t *data = NULL, *read; uint8_t *data = NULL, *read;
PixmapPtr temp_pixmap = NULL;
ScreenPtr screen; ScreenPtr screen;
glamor_screen_private *glamor_priv = glamor_screen_private *glamor_priv =
glamor_get_screen_private(pixmap->drawable.pScreen); glamor_get_screen_private(pixmap->drawable.pScreen);
glamor_gl_dispatch *dispatch; glamor_gl_dispatch *dispatch;
glamor_pixmap_fbo *temp_fbo = NULL;
screen = pixmap->drawable.pScreen; screen = pixmap->drawable.pScreen;
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv))
return TRUE; return TRUE;
if (glamor_get_tex_format_type_from_pixmap(pixmap, if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format, &format,
&type, &no_alpha, &type,
&no_revert)) { &no_alpha,
&revert,
&swap_rb, 0)) {
ErrorF("Unknown pixmap depth %d.\n", ErrorF("Unknown pixmap depth %d.\n",
pixmap->drawable.depth); pixmap->drawable.depth);
assert(0); // Should never happen. assert(0); // Should never happen.
@ -692,11 +705,11 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
glamor_validate_pixmap(pixmap); glamor_validate_pixmap(pixmap);
if (glamor_priv->gl_flavor == GLAMOR_GL_ES2 if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
&& (!glamor_tex_format_is_readable(format) || !no_revert)) { && (swap_rb != SWAP_NONE_DOWNLOADING || revert != REVERT_NONE)) {
temp_pixmap = if (!(temp_fbo = glamor_es2_pixmap_read_prepare(pixmap, format,
glamor_es2_pixmap_read_prepare(pixmap, &format, type, no_alpha,
&type, no_alpha, revert, swap_rb)))
no_revert); return FALSE;
} }
switch (access) { switch (access) {
case GLAMOR_ACCESS_RO: case GLAMOR_ACCESS_RO:
@ -807,8 +820,8 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
pixmap_priv->gl_fbo = GLAMOR_FBO_DOWNLOADED; pixmap_priv->gl_fbo = GLAMOR_FBO_DOWNLOADED;
pixmap->devPrivate.ptr = data; pixmap->devPrivate.ptr = data;
if (temp_pixmap) if (temp_fbo != NULL)
glamor_destroy_pixmap(temp_pixmap); glamor_destroy_fbo(temp_fbo);
return TRUE; return TRUE;
} }

View File

@ -182,7 +182,12 @@ struct glamor_saved_procs {
UnrealizeGlyphProcPtr unrealize_glyph; UnrealizeGlyphProcPtr unrealize_glyph;
}; };
#ifdef GLAMOR_GLES2
#define CACHE_FORMAT_COUNT 3
#else
#define CACHE_FORMAT_COUNT 1 #define CACHE_FORMAT_COUNT 1
#endif
#define CACHE_BUCKET_WCOUNT 4 #define CACHE_BUCKET_WCOUNT 4
#define CACHE_BUCKET_HCOUNT 4 #define CACHE_BUCKET_HCOUNT 4
@ -221,7 +226,7 @@ typedef struct glamor_screen_private {
/* shaders to restore a texture to another texture.*/ /* shaders to restore a texture to another texture.*/
GLint finish_access_prog[2]; GLint finish_access_prog[2];
GLint finish_access_no_revert[2]; GLint finish_access_revert[2];
GLint finish_access_swap_rb[2]; GLint finish_access_swap_rb[2];
/* glamor_tile */ /* glamor_tile */
@ -395,9 +400,9 @@ Bool glamor_destroy_pixmap(PixmapPtr pixmap);
glamor_pixmap_fbo* glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv); glamor_pixmap_fbo* glamor_pixmap_detach_fbo(glamor_pixmap_private *pixmap_priv);
void glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo); void glamor_pixmap_attach_fbo(PixmapPtr pixmap, glamor_pixmap_fbo *fbo);
glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv, glamor_pixmap_fbo * glamor_create_fbo_from_tex(glamor_screen_private *glamor_priv,
int w, int h, int depth, GLint tex, int flag); int w, int h, GLenum format, GLint tex, int flag);
glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv, glamor_pixmap_fbo * glamor_create_fbo(glamor_screen_private *glamor_priv,
int w, int h, int depth, int flag); int w, int h, GLenum format, int flag);
void glamor_destroy_fbo(glamor_pixmap_fbo *fbo); void glamor_destroy_fbo(glamor_pixmap_fbo *fbo);
void glamor_purge_fbo(glamor_pixmap_fbo *fbo); void glamor_purge_fbo(glamor_pixmap_fbo *fbo);
@ -451,6 +456,7 @@ void glamor_get_color_4f_from_pixel(PixmapPtr pixmap,
int glamor_set_destination_pixmap(PixmapPtr pixmap); int glamor_set_destination_pixmap(PixmapPtr pixmap);
int glamor_set_destination_pixmap_priv(glamor_pixmap_private * int glamor_set_destination_pixmap_priv(glamor_pixmap_private *
pixmap_priv); pixmap_priv);
void glamor_set_destination_pixmap_fbo(glamor_pixmap_fbo *);
/* nc means no check. caller must ensure this pixmap has valid fbo. /* nc means no check. caller must ensure this pixmap has valid fbo.
* usually use the GLAMOR_PIXMAP_PRIV_HAS_FBO firstly. * usually use the GLAMOR_PIXMAP_PRIV_HAS_FBO firstly.
@ -458,10 +464,9 @@ int glamor_set_destination_pixmap_priv(glamor_pixmap_private *
void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private * void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *
pixmap_priv); pixmap_priv);
glamor_pixmap_fbo *
PixmapPtr glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum format,
glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum * format, GLenum type, int no_alpha, int revert, int swap_rb);
GLenum * type, int no_alpha, int no_revert);
void glamor_set_alu(struct glamor_gl_dispatch *dispatch, void glamor_set_alu(struct glamor_gl_dispatch *dispatch,
unsigned char alu); unsigned char alu);

View File

@ -264,8 +264,9 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
float vertices[8], texcoords[8]; float vertices[8], texcoords[8];
GLfloat xscale, yscale, txscale, tyscale; GLfloat xscale, yscale, txscale, tyscale;
GLuint tex; GLuint tex;
int no_alpha, no_revert; int no_alpha, revert;
Bool ret = FALSE; Bool ret = FALSE;
int swap_rb;
if (image_format == XYBitmap) { if (image_format == XYBitmap) {
assert(depth == 1); assert(depth == 1);
@ -289,7 +290,9 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
if (glamor_get_tex_format_type_from_pixmap(pixmap, if (glamor_get_tex_format_type_from_pixmap(pixmap,
&format, &format,
&type, &no_alpha, &type, &no_alpha,
&no_revert)) { &revert,
&swap_rb,
1)) {
glamor_fallback("unknown depth. %d \n", drawable->depth); glamor_fallback("unknown depth. %d \n", drawable->depth);
goto fail; goto fail;
} }
@ -341,10 +344,10 @@ _glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
#endif #endif
dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]); dispatch->glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
dispatch->glUniform1i(glamor_priv-> dispatch->glUniform1i(glamor_priv->
finish_access_no_revert[no_alpha], finish_access_revert[no_alpha],
no_revert); revert);
dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], dispatch->glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha],
0); swap_rb);
x += drawable->x; x += drawable->x;
y += drawable->y; y += drawable->y;

View File

@ -38,12 +38,13 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
glamor_get_screen_private(drawable->pScreen); glamor_get_screen_private(drawable->pScreen);
glamor_gl_dispatch *dispatch; glamor_gl_dispatch *dispatch;
GLenum format, type; GLenum format, type;
int no_alpha, no_revert, i; int no_alpha, revert, i;
uint8_t *drawpixels_src = (uint8_t *) src; uint8_t *drawpixels_src = (uint8_t *) src;
RegionPtr clip = fbGetCompositeClip(gc); RegionPtr clip = fbGetCompositeClip(gc);
BoxRec *pbox; BoxRec *pbox;
int x_off, y_off; int x_off, y_off;
Bool ret = FALSE; Bool ret = FALSE;
int swap_rb;
dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap); dest_pixmap_priv = glamor_get_pixmap_private(dest_pixmap);
if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) { if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(dest_pixmap_priv)) {
@ -59,7 +60,9 @@ _glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
if (glamor_get_tex_format_type_from_pixmap(dest_pixmap, if (glamor_get_tex_format_type_from_pixmap(dest_pixmap,
&format, &format,
&type, &no_alpha, &type, &no_alpha,
&no_revert)) { &revert,
&swap_rb,
1)) {
glamor_fallback("unknown depth. %d \n", drawable->depth); glamor_fallback("unknown depth. %d \n", drawable->depth);
goto fail; goto fail;
} }

View File

@ -194,14 +194,14 @@ glamor_transform_boxes(BoxPtr boxes, int nbox, int dx, int dy)
&& (_w_) < _glamor_->max_fbo_size \ && (_w_) < _glamor_->max_fbo_size \
&& (_h_) < _glamor_->max_fbo_size) && (_h_) < _glamor_->max_fbo_size)
#define glamor_check_fbo_depth(_depth_) ( \ /* For 1bpp pixmap, we don't store it as texture. */
_depth_ == 8 \ #define glamor_check_pixmap_fbo_depth(_depth_) ( \
|| _depth_ == 15 \ _depth_ == 8 \
|| _depth_ == 16 \ || _depth_ == 15 \
|| _depth_ == 24 \ || _depth_ == 16 \
|| _depth_ == 30 \ || _depth_ == 24 \
|| _depth_ == 32) || _depth_ == 30 \
|| _depth_ == 32)
#define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->is_picture == 1) #define GLAMOR_PIXMAP_PRIV_IS_PICTURE(pixmap_priv) (pixmap_priv && pixmap_priv->is_picture == 1)
#define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->gl_fbo == GLAMOR_FBO_NORMAL) #define GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv) (pixmap_priv && pixmap_priv->gl_fbo == GLAMOR_FBO_NORMAL)
@ -286,6 +286,14 @@ format_for_pixmap(PixmapPtr pixmap)
return pict_format; return pict_format;
} }
#define REVERT_NONE 0
#define REVERT_NORMAL 1
#define SWAP_NONE_DOWNLOADING 0
#define SWAP_DOWNLOADING 1
#define SWAP_UPLOADING 2
#define SWAP_NONE_UPLOADING 3
/* /*
* Map picture's format to the correct gl texture format and type. * 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. * no_alpha is used to indicate whehter we need to wire alpha to 1.
@ -297,10 +305,15 @@ static inline int
glamor_get_tex_format_type_from_pictformat(PictFormatShort format, glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
GLenum * tex_format, GLenum * tex_format,
GLenum * tex_type, GLenum * tex_type,
int *no_alpha, int *no_revert) int *no_alpha,
int *revert,
int *swap_rb,
int is_upload)
{ {
*no_alpha = 0; *no_alpha = 0;
*no_revert = 1; *revert = REVERT_NONE;
*swap_rb = is_upload ? SWAP_NONE_UPLOADING : SWAP_NONE_DOWNLOADING;
switch (format) { switch (format) {
case PICT_a1: case PICT_a1:
*tex_format = GL_COLOR_INDEX; *tex_format = GL_COLOR_INDEX;
@ -385,6 +398,18 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
} }
return 0; return 0;
} }
/* Currently, we use RGBA to represent all formats. */
inline static int cache_format(GLenum format)
{
switch (format) {
case GL_RGBA:
return 0;
default:
return -1;
}
}
#else #else
#define IS_LITTLE_ENDIAN (IMAGE_BYTE_ORDER == LSBFirst) #define IS_LITTLE_ENDIAN (IMAGE_BYTE_ORDER == LSBFirst)
@ -392,25 +417,32 @@ static inline int
glamor_get_tex_format_type_from_pictformat(PictFormatShort format, glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
GLenum * tex_format, GLenum * tex_format,
GLenum * tex_type, GLenum * tex_type,
int *no_alpha, int *no_revert) int *no_alpha,
int *revert,
int *swap_rb,
int is_upload)
{ {
int need_swap_rb = 0;
*no_alpha = 0; *no_alpha = 0;
*no_revert = IS_LITTLE_ENDIAN; *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
switch (format) { switch (format) {
case PICT_b8g8r8x8: case PICT_b8g8r8x8:
*no_alpha = 1; *no_alpha = 1;
case PICT_b8g8r8a8: case PICT_b8g8r8a8:
*tex_format = GL_BGRA; *tex_format = GL_RGBA;
*tex_type = GL_UNSIGNED_BYTE; *tex_type = GL_UNSIGNED_BYTE;
*no_revert = !IS_LITTLE_ENDIAN; need_swap_rb = 1;
*revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
break; break;
case PICT_x8r8g8b8: case PICT_x8r8g8b8:
*no_alpha = 1; *no_alpha = 1;
case PICT_a8r8g8b8: case PICT_a8r8g8b8:
*tex_format = GL_BGRA; *tex_format = GL_RGBA;
*tex_type = GL_UNSIGNED_BYTE; *tex_type = GL_UNSIGNED_BYTE;
need_swap_rb = 1;
break; break;
case PICT_x8b8g8r8: case PICT_x8b8g8r8:
@ -425,7 +457,7 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
case PICT_a2r10g10b10: case PICT_a2r10g10b10:
*tex_format = GL_BGRA; *tex_format = GL_BGRA;
*tex_type = GL_UNSIGNED_INT_10_10_10_2; *tex_type = GL_UNSIGNED_INT_10_10_10_2;
*no_revert = TRUE; *revert = REVERT_NONE;
break; break;
case PICT_x2b10g10r10: case PICT_x2b10g10r10:
@ -433,19 +465,20 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
case PICT_a2b10g10r10: case PICT_a2b10g10r10:
*tex_format = GL_RGBA; *tex_format = GL_RGBA;
*tex_type = GL_UNSIGNED_INT_10_10_10_2; *tex_type = GL_UNSIGNED_INT_10_10_10_2;
*no_revert = TRUE; *revert = REVERT_NONE;
break; break;
case PICT_r5g6b5: case PICT_r5g6b5:
*tex_format = GL_RGB; *tex_format = GL_RGB;
*tex_type = GL_UNSIGNED_SHORT_5_6_5; *tex_type = GL_UNSIGNED_SHORT_5_6_5;
*no_revert = TRUE; *revert = IS_LITTLE_ENDIAN ? REVERT_NONE : REVERT_NORMAL;
break; break;
case PICT_b5g6r5: case PICT_b5g6r5:
*tex_format = GL_RGB; *tex_format = GL_RGB;
*tex_type = GL_UNSIGNED_SHORT_5_6_5; *tex_type = GL_UNSIGNED_SHORT_5_6_5;
*no_revert = FALSE; need_swap_rb = IS_LITTLE_ENDIAN ? 1 : 0;;
break; break;
case PICT_x1b5g5r5: case PICT_x1b5g5r5:
@ -453,7 +486,7 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
case PICT_a1b5g5r5: case PICT_a1b5g5r5:
*tex_format = GL_RGBA; *tex_format = GL_RGBA;
*tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
*no_revert = TRUE; *revert = REVERT_NONE;
break; break;
case PICT_x1r5g5b5: case PICT_x1r5g5b5:
@ -461,29 +494,30 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
case PICT_a1r5g5b5: case PICT_a1r5g5b5:
*tex_format = GL_BGRA; *tex_format = GL_BGRA;
*tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV; *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
*no_revert = TRUE; *revert = REVERT_NONE;
break; break;
case PICT_a8: case PICT_a8:
*tex_format = GL_ALPHA; *tex_format = GL_ALPHA;
*tex_type = GL_UNSIGNED_BYTE; *tex_type = GL_UNSIGNED_BYTE;
*no_revert = TRUE; *revert = REVERT_NONE;
break; break;
case PICT_x4r4g4b4: case PICT_x4r4g4b4:
*no_alpha = 1; *no_alpha = 1;
case PICT_a4r4g4b4: case PICT_a4r4g4b4:
*tex_format = GL_BGRA; *tex_format = GL_RGBA;
*tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
*no_revert = TRUE; *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
need_swap_rb = 1;
break; break;
case PICT_x4b4g4r4: case PICT_x4b4g4r4:
*no_alpha = 1; *no_alpha = 1;
case PICT_a4b4g4r4: case PICT_a4b4g4r4:
*tex_format = GL_RGBA; *tex_format = GL_RGBA;
*tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV; *tex_type = GL_UNSIGNED_SHORT_4_4_4_4;
*no_revert = TRUE; *revert = IS_LITTLE_ENDIAN ? REVERT_NORMAL : REVERT_NONE;
break; break;
default: default:
@ -492,9 +526,27 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
format); format);
return -1; 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; return 0;
} }
inline static int cache_format(GLenum format)
{
switch (format) {
case GL_ALPHA:
return 2;
case GL_RGB:
return 1;
case GL_RGBA:
return 0;
default:
return -1;
}
}
#endif #endif
@ -503,7 +555,10 @@ static inline int
glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap, glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
GLenum * format, GLenum * format,
GLenum * type, GLenum * type,
int *no_alpha, int *no_revert) int *no_alpha,
int *revert,
int *swap_rb,
int is_upload)
{ {
glamor_pixmap_private *pixmap_priv; glamor_pixmap_private *pixmap_priv;
PictFormatShort pict_format; PictFormatShort pict_format;
@ -517,7 +572,9 @@ glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
return glamor_get_tex_format_type_from_pictformat(pict_format, return glamor_get_tex_format_type_from_pictformat(pict_format,
format, type, format, type,
no_alpha, no_alpha,
no_revert); revert,
swap_rb,
is_upload);
} }