glamor: Add support for solid source pictures.
This commit is contained in:
		
							parent
							
								
									1159ebb30b
								
							
						
					
					
						commit
						5915b4c0cf
					
				|  | @ -43,6 +43,8 @@ typedef struct glamor_composite_shader { | ||||||
|     GLint dest_to_dest_uniform_location; |     GLint dest_to_dest_uniform_location; | ||||||
|     GLint dest_to_source_uniform_location; |     GLint dest_to_source_uniform_location; | ||||||
|     GLint dest_to_mask_uniform_location; |     GLint dest_to_mask_uniform_location; | ||||||
|  |     GLint source_uniform_location; | ||||||
|  |     GLint mask_uniform_location; | ||||||
| } glamor_composite_shader; | } glamor_composite_shader; | ||||||
| 
 | 
 | ||||||
| typedef struct glamor_screen_private { | typedef struct glamor_screen_private { | ||||||
|  | @ -70,7 +72,7 @@ typedef struct glamor_screen_private { | ||||||
|     GLint put_image_xybitmap_bg_uniform_location; |     GLint put_image_xybitmap_bg_uniform_location; | ||||||
| 
 | 
 | ||||||
|     /* glamor_composite */ |     /* glamor_composite */ | ||||||
|     glamor_composite_shader composite_shader[2]; |     glamor_composite_shader composite_shader[8]; | ||||||
| } glamor_screen_private; | } glamor_screen_private; | ||||||
| 
 | 
 | ||||||
| typedef struct glamor_pixmap_private { | typedef struct glamor_pixmap_private { | ||||||
|  |  | ||||||
|  | @ -39,7 +39,9 @@ | ||||||
| #include "glu3/glu3.h" | #include "glu3/glu3.h" | ||||||
| 
 | 
 | ||||||
| struct shader_key { | struct shader_key { | ||||||
|  |     Bool solid_source; | ||||||
|     Bool has_mask; |     Bool has_mask; | ||||||
|  |     Bool solid_mask; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| struct blendinfo { | struct blendinfo { | ||||||
|  | @ -65,7 +67,9 @@ static struct blendinfo composite_op_info[] = { | ||||||
|     [PictOpAdd] =         {0, 0, GL_ONE,                 GL_ONE}, |     [PictOpAdd] =         {0, 0, GL_ONE,                 GL_ONE}, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| #define HAS_MASK_INDEX    1 | #define SOLID_SOURCE_INDEX	1 | ||||||
|  | #define HAS_MASK_INDEX		2 | ||||||
|  | #define SOLID_MASK_INDEX	3 | ||||||
| 
 | 
 | ||||||
| static glamor_composite_shader * | static glamor_composite_shader * | ||||||
| glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) | glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) | ||||||
|  | @ -73,8 +77,13 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) | ||||||
|     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); |     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); | ||||||
|     int index = 0; |     int index = 0; | ||||||
| 
 | 
 | ||||||
|     if (key->has_mask) |     if (key->solid_source) | ||||||
|  | 	index += SOLID_SOURCE_INDEX; | ||||||
|  |     if (key->has_mask) { | ||||||
| 	index += HAS_MASK_INDEX; | 	index += HAS_MASK_INDEX; | ||||||
|  | 	if (key->solid_mask) | ||||||
|  | 	    index += SOLID_MASK_INDEX; | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     assert(index < ARRAY_SIZE(glamor_priv->composite_shader)); |     assert(index < ARRAY_SIZE(glamor_priv->composite_shader)); | ||||||
| 
 | 
 | ||||||
|  | @ -84,31 +93,58 @@ glamor_lookup_composite_shader(ScreenPtr screen, struct shader_key *key) | ||||||
| static GLuint | static GLuint | ||||||
| glamor_create_composite_fs(struct shader_key *key) | glamor_create_composite_fs(struct shader_key *key) | ||||||
| { | { | ||||||
|     const char *header = |     const char *source_pixmap_header = | ||||||
| 	"uniform sampler2D source_sampler;\n" | 	"uniform sampler2D source_sampler;\n" | ||||||
| 	"varying vec4 source_coords;\n"; | 	"varying vec4 source_coords;\n"; | ||||||
|     const char *mask_header = |     const char *source_solid_header = | ||||||
|  | 	"uniform vec4 source;\n"; | ||||||
|  |     const char *mask_pixmap_header = | ||||||
| 	"uniform sampler2D mask_sampler;\n" | 	"uniform sampler2D mask_sampler;\n" | ||||||
| 	"varying vec4 mask_coords;\n"; | 	"varying vec4 mask_coords;\n"; | ||||||
|  |     const char *mask_solid_header = | ||||||
|  | 	"uniform vec4 mask;\n"; | ||||||
|     const char *main_opening = |     const char *main_opening = | ||||||
| 	"void main()\n" | 	"void main()\n" | ||||||
| 	"{\n" | 	"{\n"; | ||||||
| 	"	vec4 result;\n" |     const char *source_pixmap_fetch = | ||||||
| 	"	result = texture2DProj(source_sampler, source_coords.xyw);\n"; | 	"	vec4 source = texture2DProj(source_sampler, " | ||||||
|  | 	"				    source_coords.xyw);\n"; | ||||||
|  |     const char *mask_pixmap_fetch = | ||||||
|  | 	"	vec4 mask = texture2DProj(mask_sampler, mask_coords.xyw);\n"; | ||||||
|     const char *source_in_mask = |     const char *source_in_mask = | ||||||
| 	"	vec4 mask = texture2DProj(mask_sampler, mask_coords.xyw);\n" | 	"	gl_FragColor = source * mask.w;\n"; | ||||||
| 	"	result = result * mask.w;\n"; |     const char *source_only = | ||||||
|  | 	"	gl_FragColor = source;\n"; | ||||||
|     const char *main_closing = |     const char *main_closing = | ||||||
| 	"	gl_FragColor = result;\n" |  | ||||||
| 	"}\n"; | 	"}\n"; | ||||||
|     char *source; |     char *source; | ||||||
|  |     const char *source_setup = ""; | ||||||
|  |     const char *source_fetch = ""; | ||||||
|  |     const char *mask_setup = ""; | ||||||
|  |     const char *mask_fetch = ""; | ||||||
|     GLuint prog; |     GLuint prog; | ||||||
| 
 | 
 | ||||||
|     source = XNFprintf("%s%s%s%s%s", |     if (key->solid_source) { | ||||||
| 		       header, | 	source_setup = source_solid_header; | ||||||
| 		       key->has_mask ? mask_header : "", |     } else { | ||||||
|  | 	source_setup = source_pixmap_header; | ||||||
|  | 	source_fetch = source_pixmap_fetch; | ||||||
|  |     } | ||||||
|  |     if (key->has_mask) { | ||||||
|  | 	if (key->solid_mask) { | ||||||
|  | 	    mask_setup = mask_solid_header; | ||||||
|  | 	} else { | ||||||
|  | 	    mask_setup = mask_pixmap_header; | ||||||
|  | 	    mask_fetch = mask_pixmap_fetch; | ||||||
|  | 	} | ||||||
|  |     } | ||||||
|  |     source = XNFprintf("%s%s%s%s%s%s%s", | ||||||
|  | 		       source_setup, | ||||||
|  | 		       mask_setup, | ||||||
| 		       main_opening, | 		       main_opening, | ||||||
| 		       key->has_mask ? source_in_mask : "", | 		       source_fetch, | ||||||
|  | 		       mask_fetch, | ||||||
|  | 		       key->has_mask ? source_in_mask : source_only, | ||||||
| 		       main_closing); | 		       main_closing); | ||||||
| 
 | 
 | ||||||
|     prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, source); |     prog = glamor_compile_glsl_prog(GL_FRAGMENT_SHADER_ARB, source); | ||||||
|  | @ -139,12 +175,13 @@ glamor_create_composite_vs(struct shader_key *key) | ||||||
| 	"}\n"; | 	"}\n"; | ||||||
|     char *source; |     char *source; | ||||||
|     GLuint prog; |     GLuint prog; | ||||||
|  |     Bool compute_mask_coords = key->has_mask && !key->solid_mask; | ||||||
| 
 | 
 | ||||||
|     source = XNFprintf("%s%s%s%s%s", |     source = XNFprintf("%s%s%s%s%s", | ||||||
| 		       header, | 		       header, | ||||||
| 		       key->has_mask ? mask_header : "", | 		       compute_mask_coords ? mask_header : "", | ||||||
| 		       main_opening, | 		       main_opening, | ||||||
| 		       key->has_mask ? mask_coords : "", | 		       compute_mask_coords ? mask_coords : "", | ||||||
| 		       main_closing); | 		       main_closing); | ||||||
| 
 | 
 | ||||||
|     prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, source); |     prog = glamor_compile_glsl_prog(GL_VERTEX_SHADER_ARB, source); | ||||||
|  | @ -177,20 +214,31 @@ glamor_create_composite_shader(ScreenPtr screen, struct shader_key *key) | ||||||
|     shader->prog = prog; |     shader->prog = prog; | ||||||
| 
 | 
 | ||||||
|     glUseProgramObjectARB(prog); |     glUseProgramObjectARB(prog); | ||||||
|     source_sampler_uniform_location = glGetUniformLocationARB(prog, |  | ||||||
| 							      "source_sampler"); |  | ||||||
|     shader->dest_to_dest_uniform_location = |     shader->dest_to_dest_uniform_location = | ||||||
| 	glGetUniformLocationARB(prog, "dest_to_dest"); | 	glGetUniformLocationARB(prog, "dest_to_dest"); | ||||||
|     shader->dest_to_source_uniform_location = | 
 | ||||||
| 	glGetUniformLocationARB(prog, "dest_to_source"); |     if (key->solid_source) { | ||||||
|     glUniform1i(source_sampler_uniform_location, 0); | 	shader->source_uniform_location = glGetUniformLocationARB(prog, | ||||||
|  | 								  "source"); | ||||||
|  |     } else { | ||||||
|  | 	source_sampler_uniform_location = glGetUniformLocationARB(prog, | ||||||
|  | 								  "source_sampler"); | ||||||
|  | 	shader->dest_to_source_uniform_location = | ||||||
|  | 	    glGetUniformLocationARB(prog, "dest_to_source"); | ||||||
|  | 	glUniform1i(source_sampler_uniform_location, 0); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if (key->has_mask) { |     if (key->has_mask) { | ||||||
| 	mask_sampler_uniform_location = glGetUniformLocationARB(prog, | 	if (key->solid_mask) { | ||||||
| 								"mask_sampler"); | 	    shader->mask_uniform_location = glGetUniformLocationARB(prog, | ||||||
| 	glUniform1i(mask_sampler_uniform_location, 1); | 								    "mask"); | ||||||
| 	shader->dest_to_mask_uniform_location = | 	} else { | ||||||
| 	    glGetUniformLocationARB(prog, "dest_to_mask"); | 	    mask_sampler_uniform_location = glGetUniformLocationARB(prog, | ||||||
|  | 								    "mask_sampler"); | ||||||
|  | 	    glUniform1i(mask_sampler_uniform_location, 1); | ||||||
|  | 	    shader->dest_to_mask_uniform_location = | ||||||
|  | 		glGetUniformLocationARB(prog, "dest_to_mask"); | ||||||
|  | 	} | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -199,10 +247,21 @@ glamor_init_composite_shaders(ScreenPtr screen) | ||||||
| { | { | ||||||
|     struct shader_key key; |     struct shader_key key; | ||||||
| 
 | 
 | ||||||
|  |     memset(&key, 0, sizeof(key)); | ||||||
|     key.has_mask = FALSE; |     key.has_mask = FALSE; | ||||||
|     glamor_create_composite_shader(screen, &key); |     glamor_create_composite_shader(screen, &key); | ||||||
|     key.has_mask = TRUE; |     key.has_mask = TRUE; | ||||||
|     glamor_create_composite_shader(screen, &key); |     glamor_create_composite_shader(screen, &key); | ||||||
|  |     key.solid_mask = TRUE; | ||||||
|  |     glamor_create_composite_shader(screen, &key); | ||||||
|  | 
 | ||||||
|  |     key.solid_source = TRUE; | ||||||
|  |     key.has_mask = FALSE; | ||||||
|  |     glamor_create_composite_shader(screen, &key); | ||||||
|  |     key.has_mask = TRUE; | ||||||
|  |     glamor_create_composite_shader(screen, &key); | ||||||
|  |     key.solid_mask = TRUE; | ||||||
|  |     glamor_create_composite_shader(screen, &key); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
|  | @ -277,8 +336,12 @@ glamor_set_composite_op(ScreenPtr screen, | ||||||
| 
 | 
 | ||||||
| static void | static void | ||||||
| glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, | glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, | ||||||
| 			     glamor_pixmap_private *pixmap_priv) | 			     glamor_pixmap_private *pixmap_priv, | ||||||
|  | 			     GLint transform_uniform_location, | ||||||
|  | 			     int x_translate, int y_translate) | ||||||
| { | { | ||||||
|  |     GLUmat4 transform; | ||||||
|  | 
 | ||||||
|     glActiveTexture(GL_TEXTURE0 + unit); |     glActiveTexture(GL_TEXTURE0 + unit); | ||||||
|     glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); |     glBindTexture(GL_TEXTURE_2D, pixmap_priv->tex); | ||||||
|     switch (picture->repeatType) { |     switch (picture->repeatType) { | ||||||
|  | @ -313,6 +376,27 @@ glamor_set_composite_texture(ScreenPtr screen, int unit, PicturePtr picture, | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     glEnable(GL_TEXTURE_2D); |     glEnable(GL_TEXTURE_2D); | ||||||
|  | 
 | ||||||
|  |     glamor_set_composite_transform_matrix(&transform, | ||||||
|  | 					  picture, | ||||||
|  | 					  x_translate, | ||||||
|  | 					  y_translate); | ||||||
|  |     glUniformMatrix4fvARB(transform_uniform_location, 1, 0, | ||||||
|  | 			  (float *)&transform); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void | ||||||
|  | glamor_set_composite_solid(PicturePtr picture, GLint uniform_location) | ||||||
|  | { | ||||||
|  |     CARD32 c = picture->pSourcePict->solidFill.color; /* a8r8g8b8 */ | ||||||
|  |     float color[4]; /* rgba */ | ||||||
|  | 
 | ||||||
|  |     color[0] = ((c >> 16) & 0xff) / 255.0; | ||||||
|  |     color[1] = ((c >> 8) & 0xff) / 255.0; | ||||||
|  |     color[2] = ((c >> 0) & 0xff) / 255.0; | ||||||
|  |     color[3] = ((c >> 24) & 0xff) / 255.0; | ||||||
|  | 
 | ||||||
|  |     glUniform4fvARB(uniform_location, 1, color); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void | void | ||||||
|  | @ -332,10 +416,11 @@ glamor_composite(CARD8 op, | ||||||
|     ScreenPtr screen = dest->pDrawable->pScreen; |     ScreenPtr screen = dest->pDrawable->pScreen; | ||||||
|     PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); |     PixmapPtr dest_pixmap = glamor_get_drawable_pixmap(dest->pDrawable); | ||||||
|     PixmapPtr source_pixmap, mask_pixmap = NULL; |     PixmapPtr source_pixmap, mask_pixmap = NULL; | ||||||
|     glamor_pixmap_private *source_pixmap_priv, *mask_pixmap_priv = NULL; |     glamor_pixmap_private *source_pixmap_priv = NULL; | ||||||
|  |     glamor_pixmap_private *mask_pixmap_priv = NULL; | ||||||
|     struct shader_key key; |     struct shader_key key; | ||||||
|     glamor_composite_shader *shader; |     glamor_composite_shader *shader; | ||||||
|     GLUmat4 dest_to_dest, dest_to_source, dest_to_mask; |     GLUmat4 dest_to_dest; | ||||||
|     RegionRec region; |     RegionRec region; | ||||||
|     int i; |     int i; | ||||||
| 
 | 
 | ||||||
|  | @ -358,14 +443,23 @@ glamor_composite(CARD8 op, | ||||||
| 	return; | 	return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     memset(&key, 0, sizeof(key)); | ||||||
|     key.has_mask = (mask != NULL); |     key.has_mask = (mask != NULL); | ||||||
|     if (!source->pDrawable) { |     if (!source->pDrawable) { | ||||||
| 	ErrorF("source-only source\n"); | 	if (source->pSourcePict->type == SourcePictTypeSolidFill) { | ||||||
| 	goto fail; | 	    key.solid_source = TRUE; | ||||||
|  | 	} else { | ||||||
|  | 	    ErrorF("gradient source\n"); | ||||||
|  | 	    goto fail; | ||||||
|  | 	} | ||||||
|     } |     } | ||||||
|     if (mask && !mask->pDrawable) { |     if (mask && !mask->pDrawable) { | ||||||
| 	ErrorF("source-only mask\n"); | 	if (mask->pSourcePict->type == SourcePictTypeSolidFill) { | ||||||
| 	goto fail; | 	    key.solid_mask = TRUE; | ||||||
|  | 	} else { | ||||||
|  | 	    ErrorF("gradient mask\n"); | ||||||
|  | 	    goto fail; | ||||||
|  | 	} | ||||||
|     } |     } | ||||||
|     if (source->alphaMap) { |     if (source->alphaMap) { | ||||||
| 	ErrorF("source alphaMap\n"); | 	ErrorF("source alphaMap\n"); | ||||||
|  | @ -376,17 +470,19 @@ glamor_composite(CARD8 op, | ||||||
| 	goto fail; | 	goto fail; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); |     if (!key.solid_source) { | ||||||
|     source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); | 	source_pixmap = glamor_get_drawable_pixmap(source->pDrawable); | ||||||
|     if (source_pixmap == dest_pixmap) { | 	source_pixmap_priv = glamor_get_pixmap_private(source_pixmap); | ||||||
| 	ErrorF("source == dest\n"); | 	if (source_pixmap == dest_pixmap) { | ||||||
| 	goto fail; | 	    ErrorF("source == dest\n"); | ||||||
|  | 	    goto fail; | ||||||
|  | 	} | ||||||
|  | 	if (!source_pixmap_priv || source_pixmap_priv->tex == 0) { | ||||||
|  | 	    ErrorF("no FBO in source\n"); | ||||||
|  | 	    goto fail; | ||||||
|  | 	} | ||||||
|     } |     } | ||||||
|     if (!source_pixmap_priv || source_pixmap_priv->tex == 0) { |     if (mask && !key.solid_mask) { | ||||||
| 	ErrorF("no FBO in source\n"); |  | ||||||
| 	goto fail; |  | ||||||
|     } |  | ||||||
|     if (mask) { |  | ||||||
| 	mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); | 	mask_pixmap = glamor_get_drawable_pixmap(mask->pDrawable); | ||||||
| 	mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); | 	mask_pixmap_priv = glamor_get_pixmap_private(mask_pixmap); | ||||||
| 	if (mask_pixmap == dest_pixmap) { | 	if (mask_pixmap == dest_pixmap) { | ||||||
|  | @ -431,25 +527,23 @@ glamor_composite(CARD8 op, | ||||||
| 	       -1, 1); | 	       -1, 1); | ||||||
|     glUniformMatrix4fvARB(shader->dest_to_dest_uniform_location, 1, 0, |     glUniformMatrix4fvARB(shader->dest_to_dest_uniform_location, 1, 0, | ||||||
| 			  (float *)&dest_to_dest); | 			  (float *)&dest_to_dest); | ||||||
|     glamor_set_composite_transform_matrix(&dest_to_source, |  | ||||||
| 					  source, |  | ||||||
| 					  x_source - x_dest, |  | ||||||
| 					  y_source - x_dest); |  | ||||||
|     glUniformMatrix4fvARB(shader->dest_to_source_uniform_location, 1, 0, |  | ||||||
| 			  (float *)&dest_to_source); |  | ||||||
| 
 | 
 | ||||||
|     if (mask) { |     if (key.solid_source) { | ||||||
| 	glamor_set_composite_transform_matrix(&dest_to_mask, | 	glamor_set_composite_solid(source, shader->source_uniform_location); | ||||||
| 					      mask, |     } else { | ||||||
| 					      x_mask - x_dest, | 	glamor_set_composite_texture(screen, 0, source, source_pixmap_priv, | ||||||
| 					      y_mask - x_dest); | 				     shader->dest_to_source_uniform_location, | ||||||
| 	glUniformMatrix4fvARB(shader->dest_to_mask_uniform_location, 1, 0, | 				     x_source - x_dest, y_source - y_dest); | ||||||
| 			      (float *)&dest_to_mask); |     } | ||||||
|  |     if (key.has_mask) { | ||||||
|  | 	if (key.solid_mask) { | ||||||
|  | 	    glamor_set_composite_solid(mask, shader->mask_uniform_location); | ||||||
|  | 	} else { | ||||||
|  | 	    glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv, | ||||||
|  | 					 shader->dest_to_mask_uniform_location, | ||||||
|  | 					 x_mask - x_dest, y_mask - y_dest); | ||||||
|  | 	} | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     glamor_set_composite_texture(screen, 0, source, source_pixmap_priv); |  | ||||||
|     if (mask) |  | ||||||
| 	glamor_set_composite_texture(screen, 1, mask, mask_pixmap_priv); |  | ||||||
| 
 | 
 | ||||||
|     if (!miComputeCompositeRegion(®ion, |     if (!miComputeCompositeRegion(®ion, | ||||||
| 				  source, mask, dest, | 				  source, mask, dest, | ||||||
|  | @ -469,9 +563,9 @@ glamor_composite(CARD8 op, | ||||||
|     } |     } | ||||||
|     glEnd(); |     glEnd(); | ||||||
| 
 | 
 | ||||||
|     glamor_set_composite_op(screen, PictOpSrc, dest, mask); |     glDisable(GL_BLEND); | ||||||
|     glUseProgramObjectARB(0); |     glUseProgramObjectARB(0); | ||||||
| 		REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); |     REGION_UNINIT(pDst->pDrawable->pScreen, ®ion); | ||||||
| 
 | 
 | ||||||
|     return; |     return; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue