glamor: Add color conversion support by using new shader.
There are two places we need to do color conversion. 1. When upload a image data to a texture. 2. When download a texture to a memory buffer. As the color format may not be supported in GLES2. We may need to do the following two operations to convert dat. a. revert argb to bgra / abgr to rgba. b. swap argb to abgr / bgra to rgba. Signed-off-by: Zhigang Gong <zhigang.gong@gmail.com>
This commit is contained in:
		
							parent
							
								
									0eea084db5
								
							
						
					
					
						commit
						67da52ec13
					
				| 
						 | 
					@ -133,7 +133,6 @@ Bool
 | 
				
			||||||
glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
 | 
					glamor_prepare_access(DrawablePtr drawable, glamor_access_t access)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
 | 
					  PixmapPtr pixmap = glamor_get_drawable_pixmap(drawable);
 | 
				
			||||||
 | 
					 | 
				
			||||||
  return glamor_download_pixmap_to_cpu(pixmap, access);
 | 
					  return glamor_download_pixmap_to_cpu(pixmap, access);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -154,17 +153,47 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
 | 
				
			||||||
  const char *fs_source =
 | 
					  const char *fs_source =
 | 
				
			||||||
    "varying vec2 source_texture;\n"
 | 
					    "varying vec2 source_texture;\n"
 | 
				
			||||||
    "uniform sampler2D sampler;\n"
 | 
					    "uniform sampler2D sampler;\n"
 | 
				
			||||||
 | 
					    "uniform int no_revert;"
 | 
				
			||||||
 | 
					    "uniform int swap_rb;"
 | 
				
			||||||
    "void main()\n"
 | 
					    "void main()\n"
 | 
				
			||||||
    "{\n"
 | 
					    "{\n"
 | 
				
			||||||
    "	gl_FragColor = texture2D(sampler, source_texture);\n"
 | 
					    "   if (no_revert == 1) \n"
 | 
				
			||||||
 | 
					    "    { \n"
 | 
				
			||||||
 | 
					    "     if (swap_rb == 1)   \n"
 | 
				
			||||||
 | 
					    "	  gl_FragColor = texture2D(sampler, source_texture).bgra;\n"
 | 
				
			||||||
 | 
					    "     else \n"
 | 
				
			||||||
 | 
					    "	  gl_FragColor = texture2D(sampler, source_texture).rgba;\n"
 | 
				
			||||||
 | 
					    "    } \n"
 | 
				
			||||||
 | 
					    "   else \n"
 | 
				
			||||||
 | 
					    "    { \n"
 | 
				
			||||||
 | 
					    "     if (swap_rb == 1)   \n"
 | 
				
			||||||
 | 
					    "	    gl_FragColor = texture2D(sampler, source_texture).argb;\n"
 | 
				
			||||||
 | 
					    "     else \n"
 | 
				
			||||||
 | 
					    "	    gl_FragColor = texture2D(sampler, source_texture).abgr;\n"
 | 
				
			||||||
 | 
					    "    } \n"
 | 
				
			||||||
    "}\n";
 | 
					    "}\n";
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
  const char *set_alpha_source =
 | 
					  const char *set_alpha_source =
 | 
				
			||||||
    "varying vec2 source_texture;\n"
 | 
					    "varying vec2 source_texture;\n"
 | 
				
			||||||
    "uniform sampler2D sampler;\n"
 | 
					    "uniform sampler2D sampler;\n"
 | 
				
			||||||
 | 
					    "uniform int no_revert;"
 | 
				
			||||||
 | 
					    "uniform int swap_rb;"
 | 
				
			||||||
    "void main()\n"
 | 
					    "void main()\n"
 | 
				
			||||||
    "{\n"
 | 
					    "{\n"
 | 
				
			||||||
    " gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n"
 | 
					    "   if (no_revert == 1) \n"
 | 
				
			||||||
 | 
					    "    { \n"
 | 
				
			||||||
 | 
					    "     if (swap_rb == 1)   \n"
 | 
				
			||||||
 | 
					    "	  gl_FragColor = vec4(texture2D(sampler, source_texture).bgr, 1);\n"
 | 
				
			||||||
 | 
					    "     else \n"
 | 
				
			||||||
 | 
					    "	  gl_FragColor = vec4(texture2D(sampler, source_texture).rgb, 1);\n"
 | 
				
			||||||
 | 
					    "    } \n"
 | 
				
			||||||
 | 
					    "   else \n"
 | 
				
			||||||
 | 
					    "    { \n"
 | 
				
			||||||
 | 
					    "     if (swap_rb == 1)   \n"
 | 
				
			||||||
 | 
					    "	  gl_FragColor = vec4(1,  texture2D(sampler, source_texture).rgb);\n"
 | 
				
			||||||
 | 
					    "     else \n"
 | 
				
			||||||
 | 
					    "	  gl_FragColor = vec4(1, texture2D(sampler, source_texture).bgr);\n"
 | 
				
			||||||
 | 
					    "    } \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;
 | 
				
			||||||
| 
						 | 
					@ -190,17 +219,31 @@ glamor_init_finish_access_shaders(ScreenPtr screen)
 | 
				
			||||||
  glBindAttribLocation(glamor_priv->finish_access_prog[1], GLAMOR_VERTEX_SOURCE, "v_texcoord0");
 | 
					  glBindAttribLocation(glamor_priv->finish_access_prog[1], GLAMOR_VERTEX_SOURCE, "v_texcoord0");
 | 
				
			||||||
  glamor_link_glsl_prog(glamor_priv->finish_access_prog[1]);
 | 
					  glamor_link_glsl_prog(glamor_priv->finish_access_prog[1]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  glamor_priv->finish_access_no_revert[0] = 
 | 
				
			||||||
 | 
					    glGetUniformLocation(glamor_priv->finish_access_prog[0], "no_revert");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  glamor_priv->finish_access_swap_rb[0] = 
 | 
				
			||||||
 | 
					    glGetUniformLocation(glamor_priv->finish_access_prog[0], "swap_rb");
 | 
				
			||||||
  sampler_uniform_location =
 | 
					  sampler_uniform_location =
 | 
				
			||||||
    glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler");
 | 
					    glGetUniformLocation(glamor_priv->finish_access_prog[0], "sampler");
 | 
				
			||||||
  glUseProgram(glamor_priv->finish_access_prog[0]);
 | 
					  glUseProgram(glamor_priv->finish_access_prog[0]);
 | 
				
			||||||
  glUniform1i(sampler_uniform_location, 0);
 | 
					  glUniform1i(sampler_uniform_location, 0);
 | 
				
			||||||
 | 
					  glUniform1i(glamor_priv->finish_access_no_revert[0],1);
 | 
				
			||||||
 | 
					  glUniform1i(glamor_priv->finish_access_swap_rb[0],0);
 | 
				
			||||||
  glUseProgram(0);
 | 
					  glUseProgram(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  glamor_priv->finish_access_no_revert[1] = 
 | 
				
			||||||
 | 
					    glGetUniformLocation(glamor_priv->finish_access_prog[1], "no_revert");
 | 
				
			||||||
 | 
					  glamor_priv->finish_access_swap_rb[1] = 
 | 
				
			||||||
 | 
					    glGetUniformLocation(glamor_priv->finish_access_prog[1], "swap_rb");
 | 
				
			||||||
  sampler_uniform_location =
 | 
					  sampler_uniform_location =
 | 
				
			||||||
    glGetUniformLocation(glamor_priv->finish_access_prog[1], "sampler");
 | 
					    glGetUniformLocation(glamor_priv->finish_access_prog[1], "sampler");
 | 
				
			||||||
  glUseProgram(glamor_priv->finish_access_prog[1]);
 | 
					  glUseProgram(glamor_priv->finish_access_prog[1]);
 | 
				
			||||||
 | 
					  glUniform1i(glamor_priv->finish_access_no_revert[1],1);
 | 
				
			||||||
  glUniform1i(sampler_uniform_location, 0);
 | 
					  glUniform1i(sampler_uniform_location, 0);
 | 
				
			||||||
 | 
					  glUniform1i(glamor_priv->finish_access_swap_rb[1],0);
 | 
				
			||||||
  glUseProgram(0);
 | 
					  glUseProgram(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
| 
						 | 
					@ -224,8 +267,9 @@ glamor_finish_access(DrawablePtr drawable)
 | 
				
			||||||
    pixmap_priv->pbo_valid = FALSE;
 | 
					    pixmap_priv->pbo_valid = FALSE;
 | 
				
			||||||
    glDeleteBuffers(1, &pixmap_priv->pbo);
 | 
					    glDeleteBuffers(1, &pixmap_priv->pbo);
 | 
				
			||||||
    pixmap_priv->pbo = 0;
 | 
					    pixmap_priv->pbo = 0;
 | 
				
			||||||
  } else
 | 
					  } else {
 | 
				
			||||||
    free(pixmap->devPrivate.ptr);
 | 
					    free(pixmap->devPrivate.ptr);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pixmap->devPrivate.ptr = NULL;
 | 
					  pixmap->devPrivate.ptr = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -143,7 +143,6 @@ glamor_solid(PixmapPtr pixmap, int x, int y, int width, int height,
 | 
				
			||||||
    GLfloat color[4];
 | 
					    GLfloat color[4];
 | 
				
			||||||
    float vertices[8];
 | 
					    float vertices[8];
 | 
				
			||||||
    GLfloat xscale, yscale;
 | 
					    GLfloat xscale, yscale;
 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) {
 | 
					    if (!GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) {
 | 
				
			||||||
        glamor_fallback("dest %p has no fbo.\n", pixmap);
 | 
					        glamor_fallback("dest %p has no fbo.\n", pixmap);
 | 
				
			||||||
	goto fail;
 | 
						goto fail;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,12 +83,15 @@ glamor_validate_pixmap(PixmapPtr pixmap)
 | 
				
			||||||
void
 | 
					void
 | 
				
			||||||
glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv)
 | 
					glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb);
 | 
					//  glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb);
 | 
				
			||||||
#ifndef GLAMOR_GLES2
 | 
					 | 
				
			||||||
  glMatrixMode(GL_PROJECTION);                                                                                                                                                                  glLoadIdentity();
 | 
					 | 
				
			||||||
  glMatrixMode(GL_MODELVIEW);                                                                                                                                                                   glLoadIdentity();                                        
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  glamor_pixmap_ensure_fb(pixmap_priv->container);
 | 
				
			||||||
 | 
					#ifndef GLAMOR_GLES2
 | 
				
			||||||
 | 
					  glMatrixMode(GL_PROJECTION);
 | 
				
			||||||
 | 
					  glLoadIdentity();
 | 
				
			||||||
 | 
					  glMatrixMode(GL_MODELVIEW);
 | 
				
			||||||
 | 
					  glLoadIdentity();                                        
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  glViewport(0, 0,
 | 
					  glViewport(0, 0,
 | 
				
			||||||
	     pixmap_priv->container->drawable.width,
 | 
						     pixmap_priv->container->drawable.width,
 | 
				
			||||||
	     pixmap_priv->container->drawable.height);
 | 
						     pixmap_priv->container->drawable.height);
 | 
				
			||||||
| 
						 | 
					@ -199,7 +202,7 @@ glamor_set_alu(unsigned char alu)
 | 
				
			||||||
 * Upload pixmap to a specified texture.
 | 
					 * Upload pixmap to a specified texture.
 | 
				
			||||||
 * This texture may not be the one attached to it.
 | 
					 * This texture may not be the one attached to it.
 | 
				
			||||||
 **/
 | 
					 **/
 | 
				
			||||||
 | 
					int in_restore = 0;
 | 
				
			||||||
static void 
 | 
					static void 
 | 
				
			||||||
__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, GLuint tex)
 | 
					__glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type, GLuint tex)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -225,7 +228,6 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
 | 
					  if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
 | 
				
			||||||
    iformat = format;
 | 
					    iformat = format;
 | 
				
			||||||
    type = GL_UNSIGNED_BYTE;
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  stride = pixmap->devKind;
 | 
					  stride = pixmap->devKind;
 | 
				
			||||||
| 
						 | 
					@ -264,7 +266,8 @@ __glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, GLenum type,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, 
 | 
					_glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format, 
 | 
				
			||||||
                                 GLenum type, int no_alpha, int flip)
 | 
					                                 GLenum type, int no_alpha, int no_revert, 
 | 
				
			||||||
 | 
					                                 int flip)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
 | 
					  glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
 | 
				
			||||||
| 
						 | 
					@ -290,8 +293,7 @@ _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 && !need_flip) {
 | 
					 | 
				
			||||||
    __glamor_upload_pixmap_to_texture(pixmap, format, type, pixmap_priv->tex);
 | 
					    __glamor_upload_pixmap_to_texture(pixmap, format, type, pixmap_priv->tex);
 | 
				
			||||||
    return;
 | 
					    return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					@ -303,14 +305,6 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
 | 
				
			||||||
    ptexcoords = texcoords_inv;
 | 
					    ptexcoords = texcoords_inv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* Slow path, we need to flip y or wire alpha to 1. */
 | 
					  /* Slow path, we need to flip y or wire alpha to 1. */
 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
  glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices);
 | 
					 | 
				
			||||||
  glEnableClientState(GL_VERTEX_ARRAY);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  glClientActiveTexture(GL_TEXTURE0);
 | 
					 | 
				
			||||||
  glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, ptexcoords);
 | 
					 | 
				
			||||||
  glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
  glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
 | 
					  glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
 | 
				
			||||||
                        2 * sizeof(float),
 | 
					                        2 * sizeof(float),
 | 
				
			||||||
                        vertices);
 | 
					                        vertices);
 | 
				
			||||||
| 
						 | 
					@ -319,10 +313,8 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
 | 
				
			||||||
                        2 * sizeof(float),
 | 
					                        2 * sizeof(float),
 | 
				
			||||||
                        ptexcoords);
 | 
					                        ptexcoords);
 | 
				
			||||||
  glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 | 
					  glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  glBindFramebuffer(GL_FRAMEBUFFER, pixmap_priv->fb);
 | 
					 | 
				
			||||||
  glViewport(0, 0, pixmap->drawable.width, pixmap->drawable.height);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 | 
				
			||||||
  glGenTextures(1, &tex);
 | 
					  glGenTextures(1, &tex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  __glamor_upload_pixmap_to_texture(pixmap, format, type, tex);
 | 
					  __glamor_upload_pixmap_to_texture(pixmap, format, type, tex);
 | 
				
			||||||
| 
						 | 
					@ -331,12 +323,18 @@ _glamor_upload_pixmap_to_texture(PixmapPtr pixmap, GLenum format,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 | 
					  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 | 
				
			||||||
  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 | 
					  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 | 
				
			||||||
 | 
					#ifndef GLAMOR_GLES2
 | 
				
			||||||
  glEnable(GL_TEXTURE_2D);
 | 
					  glEnable(GL_TEXTURE_2D);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
 | 
					  glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
 | 
				
			||||||
 | 
					  glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert);
 | 
				
			||||||
 | 
					      glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha],0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 | 
					  glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GLAMOR_GLES2
 | 
				
			||||||
  glDisable(GL_TEXTURE_2D);
 | 
					  glDisable(GL_TEXTURE_2D);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  glUseProgram(0);
 | 
					  glUseProgram(0);
 | 
				
			||||||
  glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
 | 
					  glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
 | 
				
			||||||
  glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 | 
					  glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 | 
				
			||||||
| 
						 | 
					@ -386,7 +384,7 @@ glamor_pixmap_ensure_fb(PixmapPtr pixmap)
 | 
				
			||||||
 * 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)
 | 
					glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha, int no_revert)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  int need_fbo;
 | 
					  int need_fbo;
 | 
				
			||||||
  glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
 | 
					  glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
 | 
				
			||||||
| 
						 | 
					@ -402,7 +400,7 @@ glamor_pixmap_upload_prepare(PixmapPtr pixmap, int no_alpha)
 | 
				
			||||||
  if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) 
 | 
					  if (GLAMOR_PIXMAP_PRIV_HAS_FBO(pixmap_priv)) 
 | 
				
			||||||
    return 0; 
 | 
					    return 0; 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (no_alpha != 0 || !glamor_priv->yInverted)
 | 
					  if (no_alpha != 0 || no_revert == 0 || !glamor_priv->yInverted)
 | 
				
			||||||
    need_fbo = 1;
 | 
					    need_fbo = 1;
 | 
				
			||||||
  else
 | 
					  else
 | 
				
			||||||
    need_fbo = 0;
 | 
					    need_fbo = 0;
 | 
				
			||||||
| 
						 | 
					@ -427,16 +425,17 @@ 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;
 | 
					  int no_alpha, no_revert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (glamor_get_tex_format_type_from_pixmap(pixmap, 
 | 
					  if (glamor_get_tex_format_type_from_pixmap(pixmap, 
 | 
				
			||||||
					     &format, 
 | 
										     &format, 
 | 
				
			||||||
					     &type, 
 | 
										     &type, 
 | 
				
			||||||
					     &no_alpha)) {
 | 
										     &no_alpha,
 | 
				
			||||||
 | 
					                                             &no_revert)) {
 | 
				
			||||||
    glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
 | 
					    glamor_fallback("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
 | 
				
			||||||
    return GLAMOR_UPLOAD_FAILED;
 | 
					    return GLAMOR_UPLOAD_FAILED;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (glamor_pixmap_upload_prepare(pixmap, no_alpha))
 | 
					  if (glamor_pixmap_upload_prepare(pixmap, no_alpha, no_revert))
 | 
				
			||||||
    return GLAMOR_UPLOAD_FAILED;
 | 
					    return GLAMOR_UPLOAD_FAILED;
 | 
				
			||||||
  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", 
 | 
				
			||||||
| 
						 | 
					@ -444,7 +443,7 @@ glamor_upload_pixmap_to_texture(PixmapPtr pixmap)
 | 
				
			||||||
		      pixmap->drawable.width, 
 | 
							      pixmap->drawable.width, 
 | 
				
			||||||
		      pixmap->drawable.height,
 | 
							      pixmap->drawable.height,
 | 
				
			||||||
		      pixmap->drawable.depth);
 | 
							      pixmap->drawable.depth);
 | 
				
			||||||
  _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, 1);
 | 
					  _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, no_revert, 1);
 | 
				
			||||||
  return GLAMOR_UPLOAD_DONE;
 | 
					  return GLAMOR_UPLOAD_DONE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -468,18 +467,101 @@ void
 | 
				
			||||||
glamor_restore_pixmap_to_texture(PixmapPtr pixmap)
 | 
					glamor_restore_pixmap_to_texture(PixmapPtr pixmap)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  GLenum format, type;
 | 
					  GLenum format, type;
 | 
				
			||||||
  int no_alpha;
 | 
					  int no_alpha, no_revert;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (glamor_get_tex_format_type_from_pixmap(pixmap, 
 | 
					  if (glamor_get_tex_format_type_from_pixmap(pixmap, 
 | 
				
			||||||
					     &format, 
 | 
										     &format, 
 | 
				
			||||||
					     &type, 
 | 
										     &type, 
 | 
				
			||||||
					     &no_alpha)) {
 | 
										     &no_alpha, 
 | 
				
			||||||
 | 
					                                             &no_revert)) {
 | 
				
			||||||
    ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
 | 
					    ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
 | 
				
			||||||
    assert(0);
 | 
					    assert(0);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, 1);
 | 
					
 | 
				
			||||||
 | 
					  in_restore = 1;
 | 
				
			||||||
 | 
					  _glamor_upload_pixmap_to_texture(pixmap, format, type, no_alpha, no_revert, 1);
 | 
				
			||||||
 | 
					  in_restore = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* 
 | 
				
			||||||
 | 
					 * as gles2 only support a very small set of color format and
 | 
				
			||||||
 | 
					 * type when do glReadPixel,  
 | 
				
			||||||
 | 
					 * Before we use glReadPixels to get back a textured pixmap, 
 | 
				
			||||||
 | 
					 * Use shader to convert it to a supported format and thus
 | 
				
			||||||
 | 
					 * get a new temporary pixmap returned.
 | 
				
			||||||
 | 
					 * */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PixmapPtr
 | 
				
			||||||
 | 
					glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, 
 | 
				
			||||||
 | 
					                               GLenum *type, int no_alpha, int no_revert)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    glamor_pixmap_private *source_priv;
 | 
				
			||||||
 | 
					    glamor_screen_private *glamor_priv;
 | 
				
			||||||
 | 
					    ScreenPtr screen;
 | 
				
			||||||
 | 
					    PixmapPtr temp_pixmap;
 | 
				
			||||||
 | 
					    glamor_pixmap_private *temp_pixmap_priv;
 | 
				
			||||||
 | 
					    static float vertices[8] = {-1, -1,
 | 
				
			||||||
 | 
								      1, -1,
 | 
				
			||||||
 | 
								      1,  1,
 | 
				
			||||||
 | 
								      -1,  1};
 | 
				
			||||||
 | 
					    static float texcoords[8] = {0, 0,
 | 
				
			||||||
 | 
									   1, 0,
 | 
				
			||||||
 | 
									   1, 1,
 | 
				
			||||||
 | 
									   0, 1};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int swap_rb = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    screen = source->drawable.pScreen;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    glamor_priv = glamor_get_screen_private(screen);
 | 
				
			||||||
 | 
					    source_priv = glamor_get_pixmap_private(source);
 | 
				
			||||||
 | 
					    if (*format == GL_BGRA) {
 | 
				
			||||||
 | 
					      *format = GL_RGBA;
 | 
				
			||||||
 | 
					      swap_rb = 1;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    temp_pixmap = (*screen->CreatePixmap)(screen,
 | 
				
			||||||
 | 
								                  source->drawable.width,
 | 
				
			||||||
 | 
										  source->drawable.height,
 | 
				
			||||||
 | 
										  source->drawable.depth,
 | 
				
			||||||
 | 
										  0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    temp_pixmap_priv = glamor_get_pixmap_private(temp_pixmap);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    glBindTexture(GL_TEXTURE_2D, temp_pixmap_priv->tex);
 | 
				
			||||||
 | 
					    glTexImage2D(GL_TEXTURE_2D, 0, *format, source->drawable.width, 
 | 
				
			||||||
 | 
							 source->drawable.height, 0,
 | 
				
			||||||
 | 
							 *format, *type, NULL);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    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),
 | 
				
			||||||
 | 
					                        texcoords);
 | 
				
			||||||
 | 
					    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    glActiveTexture(GL_TEXTURE0);
 | 
				
			||||||
 | 
					    glBindTexture(GL_TEXTURE_2D, source_priv->tex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    glamor_set_destination_pixmap_priv_nc(temp_pixmap_priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
 | 
				
			||||||
 | 
					    glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_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);
 | 
				
			||||||
 | 
					    glUseProgram(0);
 | 
				
			||||||
 | 
					    glFlush();
 | 
				
			||||||
 | 
					    return temp_pixmap; 
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Move a pixmap to CPU memory.
 | 
					 * Move a pixmap to CPU memory.
 | 
				
			||||||
| 
						 | 
					@ -497,18 +579,21 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
 | 
				
			||||||
  glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
 | 
					  glamor_pixmap_private *pixmap_priv = 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;
 | 
					  int no_alpha, no_revert;
 | 
				
			||||||
  uint8_t *data = NULL, *read;
 | 
					  uint8_t *data = NULL, *read;
 | 
				
			||||||
 | 
					  PixmapPtr temp_pixmap = NULL;
 | 
				
			||||||
 | 
					  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);
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  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, 
 | 
										     &type, 
 | 
				
			||||||
					     &no_alpha)) {
 | 
										     &no_alpha,
 | 
				
			||||||
 | 
					                                             &no_revert)) {
 | 
				
			||||||
    ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
 | 
					    ErrorF("Unknown pixmap depth %d.\n", pixmap->drawable.depth);
 | 
				
			||||||
    assert(0);  // Should never happen.
 | 
					    assert(0);  // Should never happen.
 | 
				
			||||||
    return FALSE;
 | 
					    return FALSE;
 | 
				
			||||||
| 
						 | 
					@ -521,13 +606,21 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
 | 
				
			||||||
		      pixmap->drawable.width, 
 | 
							      pixmap->drawable.width, 
 | 
				
			||||||
		      pixmap->drawable.height,
 | 
							      pixmap->drawable.height,
 | 
				
			||||||
		      pixmap->drawable.depth);
 | 
							      pixmap->drawable.depth);
 | 
				
			||||||
 
 | 
					
 | 
				
			||||||
  stride = pixmap->devKind;
 | 
					  stride = pixmap->devKind;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 | 
					  glamor_set_destination_pixmap_priv_nc(pixmap_priv);
 | 
				
			||||||
  /* XXX we may don't need to validate it on GPU here,
 | 
					  /* XXX we may don't need to validate it on GPU here,
 | 
				
			||||||
   * we can just validate it on CPU. */
 | 
					   * we can just validate it on CPU. */
 | 
				
			||||||
  glamor_validate_pixmap(pixmap); 
 | 
					  glamor_validate_pixmap(pixmap); 
 | 
				
			||||||
  switch (access) {
 | 
					 
 | 
				
			||||||
 | 
					  if (glamor_priv->gl_flavor == GLAMOR_GL_ES2
 | 
				
			||||||
 | 
					    && ((format != GL_RGBA && format != GL_RGB && format != GL_ALPHA) || no_revert != 1)) {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    temp_pixmap = glamor_es2_pixmap_read_prepare(pixmap, &format, &type, no_alpha, no_revert);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  } 
 | 
				
			||||||
 | 
					 switch (access) {
 | 
				
			||||||
  case GLAMOR_ACCESS_RO:
 | 
					  case GLAMOR_ACCESS_RO:
 | 
				
			||||||
    gl_access = GL_READ_ONLY;
 | 
					    gl_access = GL_READ_ONLY;
 | 
				
			||||||
    gl_usage = GL_STREAM_READ;
 | 
					    gl_usage = GL_STREAM_READ;
 | 
				
			||||||
| 
						 | 
					@ -544,9 +637,11 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
 | 
				
			||||||
    ErrorF("Glamor: Invalid access code. %d\n", access);
 | 
					    ErrorF("Glamor: Invalid access code. %d\n", access);
 | 
				
			||||||
    assert(0);
 | 
					    assert(0);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (glamor_priv->gl_flavor == GLAMOR_GL_ES2)
 | 
					  if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
 | 
				
			||||||
    data = malloc(stride * pixmap->drawable.height);
 | 
					    data = malloc(stride * pixmap->drawable.height);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
  row_length = (stride * 8) / pixmap->drawable.bitsPerPixel;
 | 
					  row_length = (stride * 8) / pixmap->drawable.bitsPerPixel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
 | 
					  if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
 | 
				
			||||||
    glPixelStorei(GL_PACK_ALIGNMENT, 1);
 | 
					    glPixelStorei(GL_PACK_ALIGNMENT, 1);
 | 
				
			||||||
    glPixelStorei(GL_PACK_ROW_LENGTH, row_length);
 | 
					    glPixelStorei(GL_PACK_ROW_LENGTH, row_length);
 | 
				
			||||||
| 
						 | 
					@ -582,8 +677,10 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    glBindBuffer (GL_PIXEL_PACK_BUFFER, 0);
 | 
					    glBindBuffer (GL_PIXEL_PACK_BUFFER, 0);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
 | 
					    if (type == GL_UNSIGNED_SHORT_1_5_5_5_REV)
 | 
				
			||||||
 | 
					      type = GL_UNSIGNED_SHORT_5_5_5_1;
 | 
				
			||||||
    glReadPixels (0, 0,
 | 
					    glReadPixels (0, 0,
 | 
				
			||||||
                    row_length, pixmap->drawable.height,
 | 
					                    pixmap->drawable.width, pixmap->drawable.height,
 | 
				
			||||||
                    format, type, data);
 | 
					                    format, type, data);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
| 
						 | 
					@ -614,6 +711,12 @@ glamor_download_pixmap_to_cpu(PixmapPtr pixmap, glamor_access_t access)
 | 
				
			||||||
  glBindFramebuffer(GL_FRAMEBUFFER, 0);
 | 
					  glBindFramebuffer(GL_FRAMEBUFFER, 0);
 | 
				
			||||||
done:
 | 
					done:
 | 
				
			||||||
  pixmap->devPrivate.ptr = data;
 | 
					  pixmap->devPrivate.ptr = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (temp_pixmap) { 
 | 
				
			||||||
 | 
					      glFlush();
 | 
				
			||||||
 | 
					      (*screen->DestroyPixmap)(temp_pixmap);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return TRUE;
 | 
					  return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,6 +43,7 @@
 | 
				
			||||||
#define GL_UNSIGNED_INT_8_8_8_8                 0x8035
 | 
					#define GL_UNSIGNED_INT_8_8_8_8                 0x8035
 | 
				
			||||||
#define GL_UNSIGNED_INT_8_8_8_8_REV             0x8367
 | 
					#define GL_UNSIGNED_INT_8_8_8_8_REV             0x8367
 | 
				
			||||||
#define GL_UNSIGNED_INT_2_10_10_10_REV          0x8368
 | 
					#define GL_UNSIGNED_INT_2_10_10_10_REV          0x8368
 | 
				
			||||||
 | 
					#define GL_UNSIGNED_INT_10_10_10_2              0x8036
 | 
				
			||||||
#define GL_UNSIGNED_SHORT_5_6_5_REV             0x8364
 | 
					#define GL_UNSIGNED_SHORT_5_6_5_REV             0x8364
 | 
				
			||||||
#define GL_UNSIGNED_SHORT_1_5_5_5_REV           0x8366
 | 
					#define GL_UNSIGNED_SHORT_1_5_5_5_REV           0x8366
 | 
				
			||||||
#define GL_UNSIGNED_SHORT_4_4_4_4_REV           0x8365
 | 
					#define GL_UNSIGNED_SHORT_4_4_4_4_REV           0x8365
 | 
				
			||||||
| 
						 | 
					@ -236,6 +237,8 @@ typedef struct glamor_screen_private {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* glamor_finishaccess */
 | 
					  /* glamor_finishaccess */
 | 
				
			||||||
  GLint finish_access_prog[2];
 | 
					  GLint finish_access_prog[2];
 | 
				
			||||||
 | 
					  GLint finish_access_no_revert[2];
 | 
				
			||||||
 | 
					  GLint finish_access_swap_rb[2];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /* glamor_solid */
 | 
					  /* glamor_solid */
 | 
				
			||||||
  GLint solid_prog;
 | 
					  GLint solid_prog;
 | 
				
			||||||
| 
						 | 
					@ -408,13 +411,16 @@ format_for_pixmap(PixmapPtr pixmap)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Return 0 if find a matched texture type. Otherwise return -1.
 | 
					 * Return 0 if find a matched texture type. Otherwise return -1.
 | 
				
			||||||
 **/
 | 
					 **/
 | 
				
			||||||
 | 
					#ifndef GLAMOR_GLES2
 | 
				
			||||||
static inline int 
 | 
					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_alpha,
 | 
				
			||||||
 | 
					                                           int *no_revert)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  *no_alpha = 0;
 | 
					  *no_alpha = 0;
 | 
				
			||||||
 | 
					  *no_revert = 1;
 | 
				
			||||||
  switch (format) {
 | 
					  switch (format) {
 | 
				
			||||||
  case PICT_a1:
 | 
					  case PICT_a1:
 | 
				
			||||||
    *tex_format = GL_COLOR_INDEX;
 | 
					    *tex_format = GL_COLOR_INDEX;
 | 
				
			||||||
| 
						 | 
					@ -497,13 +503,125 @@ glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return 0;
 | 
					  return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
 | 
					#define IS_LITTLE_ENDIAN  (IMAGE_BYTE_ORDER == LSBFirst)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline int 
 | 
				
			||||||
 | 
					glamor_get_tex_format_type_from_pictformat(PictFormatShort format,
 | 
				
			||||||
 | 
										   GLenum *tex_format, 
 | 
				
			||||||
 | 
										   GLenum *tex_type,
 | 
				
			||||||
 | 
										   int *no_alpha,
 | 
				
			||||||
 | 
					                                           int *no_revert)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  *no_alpha = 0;
 | 
				
			||||||
 | 
					  *no_revert = IS_LITTLE_ENDIAN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  switch (format) {
 | 
				
			||||||
 | 
					  case PICT_b8g8r8x8:
 | 
				
			||||||
 | 
					    *no_alpha = 1;
 | 
				
			||||||
 | 
					  case PICT_b8g8r8a8:
 | 
				
			||||||
 | 
					    *tex_format = GL_BGRA;
 | 
				
			||||||
 | 
					    *tex_type = GL_UNSIGNED_BYTE;
 | 
				
			||||||
 | 
					    *no_revert = !IS_LITTLE_ENDIAN;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  case PICT_x8r8g8b8:
 | 
				
			||||||
 | 
					    *no_alpha = 1;
 | 
				
			||||||
 | 
					  case PICT_a8r8g8b8:
 | 
				
			||||||
 | 
					    *tex_format = GL_BGRA;
 | 
				
			||||||
 | 
					    *tex_type = GL_UNSIGNED_BYTE;
 | 
				
			||||||
 | 
					    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_BGRA;
 | 
				
			||||||
 | 
					    *tex_type = GL_UNSIGNED_INT_10_10_10_2;
 | 
				
			||||||
 | 
					    *no_revert = TRUE;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  case PICT_x2b10g10r10:
 | 
				
			||||||
 | 
					    *no_alpha = 1;
 | 
				
			||||||
 | 
					  case PICT_a2b10g10r10:
 | 
				
			||||||
 | 
					    *tex_format = GL_RGBA;
 | 
				
			||||||
 | 
					    *tex_type = GL_UNSIGNED_INT_10_10_10_2;
 | 
				
			||||||
 | 
					    *no_revert = TRUE;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  case PICT_r5g6b5:
 | 
				
			||||||
 | 
					    *tex_format = GL_RGB;
 | 
				
			||||||
 | 
					    *tex_type = GL_UNSIGNED_SHORT_5_6_5;
 | 
				
			||||||
 | 
					    *no_revert = TRUE;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  case PICT_b5g6r5:
 | 
				
			||||||
 | 
					    *tex_format = GL_RGB;
 | 
				
			||||||
 | 
					    *tex_type = GL_UNSIGNED_SHORT_5_6_5;
 | 
				
			||||||
 | 
					    *no_revert = FALSE;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  case PICT_x1b5g5r5:
 | 
				
			||||||
 | 
					    *no_alpha = 1;
 | 
				
			||||||
 | 
					  case PICT_a1b5g5r5:
 | 
				
			||||||
 | 
					    *tex_format = GL_RGBA;
 | 
				
			||||||
 | 
					    *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
 | 
				
			||||||
 | 
					    *no_revert = TRUE;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					               
 | 
				
			||||||
 | 
					  case PICT_x1r5g5b5:
 | 
				
			||||||
 | 
					    *no_alpha = 1;
 | 
				
			||||||
 | 
					  case PICT_a1r5g5b5:
 | 
				
			||||||
 | 
					    *tex_format = GL_BGRA;
 | 
				
			||||||
 | 
					    *tex_type = GL_UNSIGNED_SHORT_1_5_5_5_REV;
 | 
				
			||||||
 | 
					    *no_revert = TRUE;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  case PICT_a8:
 | 
				
			||||||
 | 
					    *tex_format = GL_ALPHA;
 | 
				
			||||||
 | 
					    *tex_type = GL_UNSIGNED_BYTE;
 | 
				
			||||||
 | 
					    *no_revert = TRUE;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  case PICT_x4r4g4b4:
 | 
				
			||||||
 | 
					    *no_alpha = 1;
 | 
				
			||||||
 | 
					  case PICT_a4r4g4b4:
 | 
				
			||||||
 | 
					    *tex_format = GL_BGRA;
 | 
				
			||||||
 | 
					    *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
 | 
				
			||||||
 | 
					    *no_revert = TRUE;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  case PICT_x4b4g4r4:
 | 
				
			||||||
 | 
					    *no_alpha = 1;
 | 
				
			||||||
 | 
					  case PICT_a4b4g4r4:
 | 
				
			||||||
 | 
					    *tex_format = GL_RGBA;
 | 
				
			||||||
 | 
					    *tex_type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
 | 
				
			||||||
 | 
					    *no_revert = TRUE;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					  default:
 | 
				
			||||||
 | 
					    LogMessageVerb(X_INFO, 0, "fail to get matched format for %x \n", format);
 | 
				
			||||||
 | 
					    return -1;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline int 
 | 
					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 *ax)
 | 
					                                       int *no_alpha,
 | 
				
			||||||
 | 
					                                       int *no_revert)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  glamor_pixmap_private *pixmap_priv;
 | 
					  glamor_pixmap_private *pixmap_priv;
 | 
				
			||||||
  PictFormatShort pict_format;
 | 
					  PictFormatShort pict_format;
 | 
				
			||||||
| 
						 | 
					@ -515,7 +633,8 @@ glamor_get_tex_format_type_from_pixmap(PixmapPtr pixmap,
 | 
				
			||||||
    pict_format = format_for_depth(pixmap->drawable.depth);
 | 
					    pict_format = format_for_depth(pixmap->drawable.depth);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return glamor_get_tex_format_type_from_pictformat(pict_format, 
 | 
					  return glamor_get_tex_format_type_from_pictformat(pict_format, 
 | 
				
			||||||
						    format, type, ax);  
 | 
											    format, type, 
 | 
				
			||||||
 | 
					                                                    no_alpha, no_revert);  
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -658,6 +777,11 @@ int glamor_set_destination_pixmap_priv(glamor_pixmap_private *pixmap_priv);
 | 
				
			||||||
 * */
 | 
					 * */
 | 
				
			||||||
void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv);
 | 
					void glamor_set_destination_pixmap_priv_nc(glamor_pixmap_private *pixmap_priv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PixmapPtr
 | 
				
			||||||
 | 
					glamor_es2_pixmap_read_prepare(PixmapPtr source, GLenum *format, 
 | 
				
			||||||
 | 
					                               GLenum *type, int no_alpha, int no_revert);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void glamor_set_alu(unsigned char alu);
 | 
					void glamor_set_alu(unsigned char alu);
 | 
				
			||||||
Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask);
 | 
					Bool glamor_set_planemask(PixmapPtr pixmap, unsigned long planemask);
 | 
				
			||||||
void glamor_get_transform_uniform_locations(GLint prog,
 | 
					void glamor_get_transform_uniform_locations(GLint prog,
 | 
				
			||||||
| 
						 | 
					@ -870,7 +994,7 @@ glamor_picture_format_fixup(PicturePtr picture, glamor_pixmap_private *pixmap_pr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define GLAMOR_PIXMAP_DYNAMIC_UPLOAD 
 | 
					#define GLAMOR_PIXMAP_DYNAMIC_UPLOAD 
 | 
				
			||||||
#define GLAMOR_DELAYED_FILLING
 | 
					//#define GLAMOR_DELAYED_FILLING
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include"glamor_utils.h" 
 | 
					#include"glamor_utils.h" 
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -265,7 +265,7 @@ 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;
 | 
					    int no_alpha, no_revert;
 | 
				
			||||||
    if (image_format == XYBitmap) {
 | 
					    if (image_format == XYBitmap) {
 | 
				
			||||||
	assert(depth == 1);
 | 
						assert(depth == 1);
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
| 
						 | 
					@ -290,7 +290,8 @@ 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, 
 | 
					                                               &type, 
 | 
				
			||||||
                                               &no_alpha
 | 
					                                               &no_alpha,
 | 
				
			||||||
 | 
					                                               &no_revert
 | 
				
			||||||
                                               )) {
 | 
					                                               )) {
 | 
				
			||||||
      glamor_fallback("unknown depth. %d \n", 
 | 
					      glamor_fallback("unknown depth. %d \n", 
 | 
				
			||||||
                     drawable->depth);
 | 
					                     drawable->depth);
 | 
				
			||||||
| 
						 | 
					@ -300,14 +301,6 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
 | 
				
			||||||
    /* XXX consider to reuse a function to do the following work. */
 | 
					    /* XXX consider to reuse a function to do the following work. */
 | 
				
			||||||
    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 0
 | 
					 | 
				
			||||||
    glVertexPointer(2, GL_FLOAT, sizeof(float) * 2, vertices);
 | 
					 | 
				
			||||||
    glEnableClientState(GL_VERTEX_ARRAY);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    glClientActiveTexture(GL_TEXTURE0);
 | 
					 | 
				
			||||||
    glTexCoordPointer(2, GL_FLOAT, sizeof(float) * 2, texcoords);
 | 
					 | 
				
			||||||
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
 | 
					    glVertexAttribPointer(GLAMOR_VERTEX_POS, 2, GL_FLOAT, GL_FALSE,
 | 
				
			||||||
                        2 * sizeof(float),
 | 
					                        2 * sizeof(float),
 | 
				
			||||||
                        vertices);
 | 
					                        vertices);
 | 
				
			||||||
| 
						 | 
					@ -317,7 +310,6 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
 | 
				
			||||||
                        2 * sizeof(float),
 | 
					                        2 * sizeof(float),
 | 
				
			||||||
                        texcoords);
 | 
					                        texcoords);
 | 
				
			||||||
    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 | 
					    glEnableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
 | 
					    if (glamor_priv->gl_flavor == GLAMOR_GL_DESKTOP) {
 | 
				
			||||||
      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 | 
					      glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
 | 
				
			||||||
| 
						 | 
					@ -333,20 +325,25 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
 | 
				
			||||||
    glActiveTexture(GL_TEXTURE0);
 | 
					    glActiveTexture(GL_TEXTURE0);
 | 
				
			||||||
    glBindTexture(GL_TEXTURE_2D, tex);
 | 
					    glBindTexture(GL_TEXTURE_2D, tex);
 | 
				
			||||||
    if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
 | 
					    if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
 | 
				
			||||||
      type = GL_UNSIGNED_BYTE;
 | 
					 | 
				
			||||||
      iformat = format;
 | 
					      iformat = format;
 | 
				
			||||||
    } 
 | 
					    } 
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
      iformat = GL_RGBA;
 | 
					      iformat = GL_RGBA;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glTexImage2D(GL_TEXTURE_2D, 0, iformat,
 | 
					    glTexImage2D(GL_TEXTURE_2D, 0, iformat,
 | 
				
			||||||
		 w, h, 0,
 | 
							 w, h, 0,
 | 
				
			||||||
		 format, type, bits);
 | 
							 format, type, bits);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 | 
					    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 | 
				
			||||||
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 | 
					    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 | 
				
			||||||
 | 
					#ifndef GLAMOR_GLES2
 | 
				
			||||||
    glEnable(GL_TEXTURE_2D);
 | 
					    glEnable(GL_TEXTURE_2D);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
 | 
					    glUseProgram(glamor_priv->finish_access_prog[no_alpha]);
 | 
				
			||||||
 | 
					    glUniform1i(glamor_priv->finish_access_no_revert[no_alpha], no_revert);
 | 
				
			||||||
 | 
					      glUniform1i(glamor_priv->finish_access_swap_rb[no_alpha], 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    x += drawable->x;
 | 
					    x += drawable->x;
 | 
				
			||||||
    y += drawable->y;
 | 
					    y += drawable->y;
 | 
				
			||||||
| 
						 | 
					@ -394,7 +391,9 @@ glamor_put_image(DrawablePtr drawable, GCPtr gc, int depth, int x, int y,
 | 
				
			||||||
	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 | 
						glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GLAMOR_GLES2
 | 
				
			||||||
    glDisable(GL_TEXTURE_2D);
 | 
					    glDisable(GL_TEXTURE_2D);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    glUseProgram(0);
 | 
					    glUseProgram(0);
 | 
				
			||||||
    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
 | 
					    glDisableVertexAttribArray(GLAMOR_VERTEX_POS);
 | 
				
			||||||
    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 | 
					    glDisableVertexAttribArray(GLAMOR_VERTEX_SOURCE);
 | 
				
			||||||
| 
						 | 
					@ -409,9 +408,9 @@ fail:
 | 
				
			||||||
    glamor_set_planemask(pixmap, ~0);
 | 
					    glamor_set_planemask(pixmap, ~0);
 | 
				
			||||||
    glamor_fallback("to %p (%c)\n",
 | 
					    glamor_fallback("to %p (%c)\n",
 | 
				
			||||||
		    drawable, glamor_get_drawable_location(drawable));
 | 
							    drawable, glamor_get_drawable_location(drawable));
 | 
				
			||||||
    if (glamor_prepare_access(drawable, GLAMOR_ACCESS_RW)) {
 | 
					    if (glamor_prepare_access(&pixmap->drawable, GLAMOR_ACCESS_RW)) {
 | 
				
			||||||
	fbPutImage(drawable, gc, depth, x, y, w, h, left_pad, image_format,
 | 
						fbPutImage(&pixmap->drawable, gc, depth, x, y, w, h, left_pad, image_format,
 | 
				
			||||||
		   bits);
 | 
							   bits);
 | 
				
			||||||
	glamor_finish_access(drawable);
 | 
						glamor_finish_access(&pixmap->drawable);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,7 +38,7 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
 | 
				
			||||||
    PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable);
 | 
					    PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(drawable);
 | 
				
			||||||
    glamor_screen_private *glamor_priv;
 | 
					    glamor_screen_private *glamor_priv;
 | 
				
			||||||
    GLenum format, type;
 | 
					    GLenum format, type;
 | 
				
			||||||
    int no_alpha, i;
 | 
					    int no_alpha, no_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;
 | 
				
			||||||
| 
						 | 
					@ -46,18 +46,23 @@ glamor_set_spans(DrawablePtr drawable, GCPtr gc, char *src,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    glamor_priv = glamor_get_screen_private(drawable->pScreen);
 | 
					    glamor_priv = glamor_get_screen_private(drawable->pScreen);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (glamor_priv->gl_flavor == GLAMOR_GL_ES2)
 | 
					    if (glamor_priv->gl_flavor == GLAMOR_GL_ES2) {
 | 
				
			||||||
 | 
					      glamor_fallback("ES2 fallback.\n");
 | 
				
			||||||
      goto fail;
 | 
					      goto fail;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (glamor_get_tex_format_type_from_pixmap(dest_pixmap,
 | 
					    if (glamor_get_tex_format_type_from_pixmap(dest_pixmap,
 | 
				
			||||||
                                               &format, 
 | 
					                                               &format, 
 | 
				
			||||||
                                               &type, 
 | 
					                                               &type, 
 | 
				
			||||||
                                               &no_alpha
 | 
					                                               &no_alpha,
 | 
				
			||||||
 | 
					                                               &no_revert
 | 
				
			||||||
                                               )) {
 | 
					                                               )) {
 | 
				
			||||||
      glamor_fallback("unknown depth. %d \n", 
 | 
					      glamor_fallback("unknown depth. %d \n", 
 | 
				
			||||||
                     drawable->depth);
 | 
					                     drawable->depth);
 | 
				
			||||||
      goto fail;
 | 
					      goto fail;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (glamor_set_destination_pixmap(dest_pixmap))
 | 
					    if (glamor_set_destination_pixmap(dest_pixmap))
 | 
				
			||||||
	goto fail;
 | 
						goto fail;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue