Default to a blend function that expects premultiplied colors
Many operations, like mixing two textures together or alpha-blending onto a destination with alpha, are done most logically if texture data is in premultiplied form. We also have many sources of premultiplied texture data, like X pixmaps, FBOs, cairo surfaces. Rather than trying to work with two different types of texture data, simplify things by always premultiplying texture data before uploading to GL. Because the default blend function is changed to accommodate this, uses of pure-color CoglMaterial need to be adapted to add premultiplication. gl/cogl-texture.c gles/cogl-texture.c: Always premultiply non-premultiplied texture data before uploading to GL. cogl-material.c cogl-material.h: Switch the default blend functions to ONE, ONE_MINUS_SRC_ALPHA so they work correctly with premultiplied data. cogl.c: Make cogl_set_source_color() premultiply the color. cogl.h.in color-material.h: Add some documentation about premultiplication and its interaction with color values. cogl-pango-render.c clutter-texture.c tests/interactive/test-cogl-offscreen.c: Use premultiplied colors. http://bugzilla.openedhand.com/show_bug.cgi?id=1406 Signed-off-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
parent
888a261999
commit
c3448314d5
@ -608,7 +608,8 @@ clutter_texture_paint (ClutterActor *self)
|
||||
clutter_actor_get_name (self) ? clutter_actor_get_name (self)
|
||||
: "unknown");
|
||||
|
||||
cogl_material_set_color4ub (priv->material, 0xff, 0xff, 0xff, paint_opacity);
|
||||
cogl_material_set_color4ub (priv->material,
|
||||
paint_opacity, paint_opacity, paint_opacity, paint_opacity);
|
||||
|
||||
clutter_actor_get_allocation_box (self, &box);
|
||||
|
||||
|
@ -138,6 +138,11 @@ gboolean cogl_is_material (CoglHandle handle);
|
||||
*
|
||||
* This is the basic color of the material, used when no lighting is enabled.
|
||||
*
|
||||
* Note that if you don't add any layers to the material then the color
|
||||
* will be blended unmodified with the destination; the default blend
|
||||
* expects premultiplied colors: for example, use (0.5, 0.0, 0.0, 0.5) for
|
||||
* semi-transparent red. See cogl_color_premultiply().
|
||||
*
|
||||
* The default value is (1.0, 1.0, 1.0, 1.0)
|
||||
*
|
||||
* Since 1.0
|
||||
@ -475,6 +480,11 @@ void cogl_material_set_alpha_test_function (CoglHandle material,
|
||||
* </programlisting>
|
||||
* </section>
|
||||
*
|
||||
* The default blend string is:
|
||||
* "RGBA = ADD (SRC_COLOR, DST_COLOR*(1-SRC_COLOR[A]))"
|
||||
* That gives normal alpha-blending when the calculated color for the material
|
||||
* is in premultiplied form.
|
||||
*
|
||||
* Returns: TRUE if the blend string was successfully parsed, and the described
|
||||
* blending is supported by the underlying driver/hardware. If there
|
||||
* was an error, it returns FALSE.
|
||||
|
@ -455,8 +455,13 @@ void cogl_set_source (CoglHandle material);
|
||||
* cogl_set_source_color:
|
||||
* @color: a #CoglColor
|
||||
*
|
||||
* Sets the source color using normalized values for each component.
|
||||
* This color will be used for any subsequent drawing operation.
|
||||
* This is a convenience function for creating a solid fill source material
|
||||
* from the given color. This color will be used for any subsequent drawing
|
||||
* operation.
|
||||
*
|
||||
* The color will be premultiplied by Cogl, so the color should be
|
||||
* non-premultiplied. For example: use (1.0, 0.0, 0.0, 0.5) for
|
||||
* semi-transparent red.
|
||||
*
|
||||
* See also cogl_set_source_color4ub() and cogl_set_source_color4f()
|
||||
* if you already have the color components.
|
||||
|
@ -109,7 +109,7 @@ cogl_material_new (void)
|
||||
material->blend_constant[2] = 0;
|
||||
material->blend_constant[3] = 0;
|
||||
#endif
|
||||
material->blend_src_factor_rgb = GL_SRC_ALPHA;
|
||||
material->blend_src_factor_rgb = GL_ONE;
|
||||
material->blend_dst_factor_rgb = GL_ONE_MINUS_SRC_ALPHA;
|
||||
material->flags |= COGL_MATERIAL_FLAG_DEFAULT_BLEND_FUNC;
|
||||
|
||||
|
@ -250,12 +250,17 @@ cogl_get_backface_culling_enabled (void)
|
||||
void
|
||||
cogl_set_source_color (const CoglColor *color)
|
||||
{
|
||||
CoglColor premultiplied;
|
||||
|
||||
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
|
||||
|
||||
/* In case cogl_set_source_texture was previously used... */
|
||||
cogl_material_remove_layer (ctx->default_material, 0);
|
||||
|
||||
cogl_material_set_color (ctx->default_material, color);
|
||||
premultiplied = *color;
|
||||
cogl_color_premultiply (&premultiplied);
|
||||
cogl_material_set_color (ctx->default_material, &premultiplied);
|
||||
|
||||
cogl_set_source (ctx->default_material);
|
||||
}
|
||||
|
||||
|
@ -1085,18 +1085,20 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format,
|
||||
GLenum glformat = 0;
|
||||
GLenum gltype = 0;
|
||||
|
||||
/* No premultiplied formats accepted by GL
|
||||
* (FIXME: latest hardware?) */
|
||||
|
||||
if (format & COGL_PREMULT_BIT)
|
||||
format = (format & COGL_UNPREMULT_MASK);
|
||||
|
||||
/* Everything else accepted
|
||||
* (FIXME: check YUV support) */
|
||||
required_format = format;
|
||||
/* If PREMULT_BIT isn't specified, that means that we premultiply
|
||||
* textures with alpha before uploading to GL; once we are in GL land,
|
||||
* everything is premultiplied.
|
||||
*
|
||||
* Everything else accepted (FIXME: check YUV support)
|
||||
*/
|
||||
if ((format & COGL_A_BIT) != 0 &&
|
||||
format != COGL_PIXEL_FORMAT_A_8)
|
||||
required_format = format | COGL_PREMULT_BIT;
|
||||
else
|
||||
required_format = format;
|
||||
|
||||
/* Find GL equivalents */
|
||||
switch (format)
|
||||
switch (format & COGL_UNPREMULT_MASK)
|
||||
{
|
||||
case COGL_PIXEL_FORMAT_A_8:
|
||||
glintformat = GL_ALPHA;
|
||||
|
@ -1184,18 +1184,20 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format,
|
||||
GLenum glformat = 0;
|
||||
GLenum gltype = 0;
|
||||
|
||||
/* No premultiplied formats accepted by GL
|
||||
* (FIXME: latest hardware?) */
|
||||
|
||||
if (format & COGL_PREMULT_BIT)
|
||||
format = (format & COGL_UNPREMULT_MASK);
|
||||
|
||||
/* Everything else accepted
|
||||
* (FIXME: check YUV support) */
|
||||
required_format = format;
|
||||
/* If PREMULT_BIT isn't specified, that means that we premultiply
|
||||
* textures with alpha before uploading to GL; once we are in GL land,
|
||||
* everything is premultiplied.
|
||||
*
|
||||
* Everything else accepted (FIXME: check YUV support)
|
||||
*/
|
||||
if ((format & COGL_A_BIT) != 0 &&
|
||||
format != COGL_PIXEL_FORMAT_A_8)
|
||||
required_format = format | COGL_PREMULT_BIT;
|
||||
else
|
||||
required_format = format;
|
||||
|
||||
/* Find GL equivalents */
|
||||
switch (format)
|
||||
switch (format & COGL_UNPREMULT_MASK)
|
||||
{
|
||||
case COGL_PIXEL_FORMAT_A_8:
|
||||
glintformat = GL_ALPHA;
|
||||
@ -1226,6 +1228,7 @@ _cogl_pixel_format_to_gl (CoglPixelFormat format,
|
||||
glformat = GL_RGBA;
|
||||
gltype = GL_UNSIGNED_BYTE;
|
||||
required_format = COGL_PIXEL_FORMAT_RGBA_8888;
|
||||
required_format |= (format & COGL_PREMULT_BIT);
|
||||
break;
|
||||
|
||||
/* The following three types of channel ordering
|
||||
|
@ -239,8 +239,10 @@ _cogl_pango_display_list_render_texture (CoglHandle material,
|
||||
const CoglColor *color,
|
||||
CoglPangoDisplayListNode *node)
|
||||
{
|
||||
CoglColor premult_color = *color;
|
||||
cogl_material_set_layer (material, 0, node->d.texture.texture);
|
||||
cogl_material_set_color (material, color);
|
||||
cogl_color_premultiply (&premult_color);
|
||||
cogl_material_set_color (material, &premult_color);
|
||||
cogl_set_source (material);
|
||||
|
||||
if (node->d.texture.vertex_buffer == COGL_INVALID_HANDLE)
|
||||
@ -311,6 +313,7 @@ _cogl_pango_display_list_render (CoglPangoDisplayList *dl,
|
||||
cogl_color_get_alpha_byte (color));
|
||||
else
|
||||
draw_color = *color;
|
||||
cogl_color_premultiply (&draw_color);
|
||||
|
||||
switch (node->type)
|
||||
{
|
||||
|
@ -124,16 +124,20 @@ cogl_pango_renderer_init (CoglPangoRenderer *priv)
|
||||
|
||||
/* The default combine mode of materials is to modulate (A x B) the texture
|
||||
* RGBA channels with the RGBA channels of the previous layer (which in our
|
||||
* case is just the solid font color)
|
||||
* case is just the font color)
|
||||
*
|
||||
* Since our glyph cache textures are component alpha textures, and so the
|
||||
* RGB channels are defined as (0, 0, 0) we don't want to modulate the RGB
|
||||
* channels, instead we want to simply replace them with our solid font
|
||||
* color...
|
||||
* Since the RGB for an alpha texture is defined as 0, this gives us:
|
||||
*
|
||||
* result.rgb = color.rgb * 0
|
||||
* result.a = color.a * texture.a
|
||||
*
|
||||
* What we want is premultiplied rgba values:
|
||||
*
|
||||
* result.rgba = color.rgb * texture.a
|
||||
* result.a = color.a * texture.a
|
||||
*/
|
||||
cogl_material_set_layer_combine (priv->glyph_material, 0, /* layer */
|
||||
"RGB = REPLACE (PREVIOUS)"
|
||||
"A = MODULATE (PREVIOUS, TEXTURE)",
|
||||
"RGBA = MODULATE (PREVIOUS, TEXTURE[A])",
|
||||
NULL);
|
||||
|
||||
priv->solid_material = cogl_material_new ();
|
||||
|
@ -106,7 +106,7 @@ test_coglbox_paint(ClutterActor *self)
|
||||
cogl_set_draw_buffer (COGL_WINDOW_BUFFER, 0);
|
||||
|
||||
material = cogl_material_new ();
|
||||
cogl_material_set_color4ub (material, 0xff, 0xff, 0xff, 0x88);
|
||||
cogl_material_set_color4ub (material, 0x88, 0x88, 0x88, 0x88);
|
||||
cogl_material_set_layer (material, 0, priv->texture_id);
|
||||
cogl_set_source (material);
|
||||
cogl_rectangle_with_texture_coords (100, 100,
|
||||
|
Loading…
Reference in New Issue
Block a user