* clutter/cogl/gles/cogl-gles2-wrapper.h (CoglGles2Wrapper): Added

uniforms for alpha testing.

	* clutter/cogl/gles/cogl-gles2-wrapper.c
	(cogl_gles2_wrapper_init): Get the uniforms for alpha testing
	settings.
	(cogl_wrap_glEnable, cogl_wrap_glDisable): Enable/disable alpha
	testing.
	(cogl_wrap_glAlphaFunc): Filled in the wrapper.

	* clutter/cogl/gles/cogl-fixed-fragment-shader.glsl: Added alpha
	testing.

	* clutter/cogl/gles/cogl-gles2-wrapper.h:
	* clutter/cogl/gles/cogl-gles2-wrapper.c
	(cogl_wrap_glGetIntegerv): Added a wrapper for glGetIntegerv so
	that it can report zero clip planes.

	* clutter/cogl/gles/cogl.c:
	* clutter/cogl/gles/cogl-texture.c: Use the wrapped version of
	glGetIntegerv

	* clutter/cogl/gles/cogl-primitives.c (_cogl_path_fill_nodes): Use
	_cogl_features_available to check for the stencil buffer instead
	of an #ifdef. The stencil buffer is available in the default
	profile for the GLES 2 simulator.
This commit is contained in:
Neil Roberts 2008-05-29 13:29:04 +00:00
parent 38c9d46a0e
commit 559495caf7
6 changed files with 275 additions and 172 deletions

View File

@ -12,6 +12,20 @@ uniform bool alpha_only;
uniform bool fog_enabled;
uniform vec4 fog_color;
/* Alpha test options */
uniform bool alpha_test_enabled;
uniform int alpha_test_func;
uniform float alpha_test_ref;
/* Alpha test functions */
const int GL_NEVER = 0x0200;
const int GL_LESS = 0x0201;
const int GL_EQUAL = 0x0202;
const int GL_LEQUAL = 0x0203;
const int GL_GREATER = 0x0204;
const int GL_NOTEQUAL = 0x0205;
const int GL_GEQUAL = 0x0206;
void
main (void)
{
@ -35,4 +49,41 @@ main (void)
if (fog_enabled)
/* Mix the calculated color with the fog color */
gl_FragColor.rgb = mix (fog_color.rgb, gl_FragColor.rgb, fog_amount);
/* Alpha testing */
if (alpha_test_enabled)
{
if (alpha_test_func == GL_NEVER)
discard;
else if (alpha_test_func == GL_LESS)
{
if (gl_FragColor.a >= alpha_test_ref)
discard;
}
else if (alpha_test_func == GL_EQUAL)
{
if (gl_FragColor.a != alpha_test_ref)
discard;
}
else if (alpha_test_func == GL_LEQUAL)
{
if (gl_FragColor.a > alpha_test_ref)
discard;
}
else if (alpha_test_func == GL_GREATER)
{
if (gl_FragColor.a <= alpha_test_ref)
discard;
}
else if (alpha_test_func == GL_NOTEQUAL)
{
if (gl_FragColor.a == alpha_test_ref)
discard;
}
else if (alpha_test_func == GL_GEQUAL)
{
if (gl_FragColor.a < alpha_test_ref)
discard;
}
}
}

View File

@ -164,6 +164,13 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
wrapper->fog_color_uniform
= glGetUniformLocation (wrapper->program, "fog_color");
wrapper->alpha_test_enabled_uniform
= glGetUniformLocation (wrapper->program, "alpha_test_enabled");
wrapper->alpha_test_func_uniform
= glGetUniformLocation (wrapper->program, "alpha_test_func");
wrapper->alpha_test_ref_uniform
= glGetUniformLocation (wrapper->program, "alpha_test_ref");
/* Always use the first texture unit */
glUniform1i (wrapper->bound_texture_uniform, 0);
@ -184,6 +191,10 @@ cogl_gles2_wrapper_init (CoglGles2Wrapper *wrapper)
cogl_wrap_glFogx (GL_FOG_START, 0);
cogl_wrap_glFogx (GL_FOG_END, 1);
cogl_wrap_glFogxv (GL_FOG_COLOR, default_fog_color);
/* Initialize alpha testing */
cogl_wrap_glDisable (GL_ALPHA_TEST);
cogl_wrap_glAlphaFunc (GL_ALWAYS, 0.0f);
}
void
@ -567,6 +578,10 @@ cogl_wrap_glEnable (GLenum cap)
glUniform1i (w->fog_enabled_uniform, GL_TRUE);
break;
case GL_ALPHA_TEST:
glUniform1i (w->alpha_test_enabled_uniform, GL_TRUE);
break;
default:
glEnable (cap);
}
@ -587,6 +602,10 @@ cogl_wrap_glDisable (GLenum cap)
glUniform1i (w->fog_enabled_uniform, GL_FALSE);
break;
case GL_ALPHA_TEST:
glUniform1i (w->alpha_test_enabled_uniform, GL_FALSE);
break;
default:
glDisable (cap);
}
@ -629,7 +648,15 @@ cogl_wrap_glDisableClientState (GLenum array)
void
cogl_wrap_glAlphaFunc (GLenum func, GLclampf ref)
{
/* FIXME */
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
if (ref < 0.0f)
ref = 0.0f;
else if (ref > 1.0f)
ref = 1.0f;
glUniform1i (w->alpha_test_func_uniform, func);
glUniform1f (w->alpha_test_ref_uniform, ref);
}
void
@ -656,6 +683,23 @@ cogl_gles2_float_array_to_fixed (int size, const GLfloat *floats,
*(fixeds++) = CLUTTER_FLOAT_TO_FIXED (*(floats++));
}
void
cogl_wrap_glGetIntegerv (GLenum pname, GLint *params)
{
_COGL_GET_GLES2_WRAPPER (w, NO_RETVAL);
switch (pname)
{
case GL_MAX_CLIP_PLANES:
*params = 0;
break;
default:
glGetIntegerv (pname, params);
break;
}
}
void
cogl_wrap_glGetFixedv (GLenum pname, GLfixed *params)
{

View File

@ -57,6 +57,10 @@ struct _CoglGles2Wrapper
GLint fog_end_uniform;
GLint fog_color_uniform;
GLint alpha_test_enabled_uniform;
GLint alpha_test_func_uniform;
GLint alpha_test_ref_uniform;
GLuint matrix_mode;
GLfloat modelview_stack[COGL_GLES2_MODELVIEW_STACK_SIZE * 16];
GLuint modelview_stack_pos;
@ -149,6 +153,7 @@ void cogl_wrap_glColor4x (GLclampx r, GLclampx g, GLclampx b, GLclampx a);
void cogl_wrap_glClipPlanex (GLenum plane, GLfixed *equation);
void cogl_wrap_glGetIntegerv (GLenum pname, GLint *params);
void cogl_wrap_glGetFixedv (GLenum pname, GLfixed *params);
void cogl_wrap_glFogx (GLenum pname, GLfixed param);
@ -191,6 +196,7 @@ void cogl_gles2_wrapper_bind_texture (GLenum target, GLuint texture,
#define cogl_wrap_glAlphaFunc glAlphaFunc
#define cogl_wrap_glColor4x glColor4x
#define cogl_wrap_glClipPlanex glClipPlanex
#define cogl_wrap_glGetIntegerv glGetIntegerv
#define cogl_wrap_glGetFixedv glGetFixedv
#define cogl_wrap_glFogx glFogx
#define cogl_wrap_glFogxv glFogxv

View File

@ -172,186 +172,188 @@ _cogl_path_fill_nodes ()
bounds_w = CLUTTER_FIXED_CEIL (ctx->path_nodes_max.x - ctx->path_nodes_min.x);
bounds_h = CLUTTER_FIXED_CEIL (ctx->path_nodes_max.y - ctx->path_nodes_min.y);
#if GOT_WORKING_STENCIL_BUFFER
GE( glClear (GL_STENCIL_BUFFER_BIT) );
if (cogl_features_available (COGL_FEATURE_STENCIL_BUFFER))
{
GE( glClear (GL_STENCIL_BUFFER_BIT) );
GE( cogl_wrap_glEnable (GL_STENCIL_TEST) );
GE( glStencilFunc (GL_ALWAYS, 0x0, 0x0) );
GE( glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT) );
GE( glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) );
GE( cogl_wrap_glEnable (GL_STENCIL_TEST) );
GE( glStencilFunc (GL_ALWAYS, 0x0, 0x0) );
GE( glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT) );
GE( glColorMask (GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE) );
cogl_enable (COGL_ENABLE_VERTEX_ARRAY
| (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0));
cogl_enable (COGL_ENABLE_VERTEX_ARRAY
| (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0));
GE( cogl_wrap_glVertexPointer (2, GL_FIXED, 0, ctx->path_nodes) );
GE( cogl_wrap_glDrawArrays (GL_TRIANGLE_FAN, 0, ctx->path_nodes_size) );
GE( cogl_wrap_glVertexPointer (2, GL_FIXED, 0, ctx->path_nodes) );
GE( cogl_wrap_glDrawArrays (GL_TRIANGLE_FAN, 0, ctx->path_nodes_size) );
GE( glStencilFunc (GL_EQUAL, 0x1, 0x1) );
GE( glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO) );
GE( glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) );
GE( glStencilFunc (GL_EQUAL, 0x1, 0x1) );
GE( glStencilOp (GL_ZERO, GL_ZERO, GL_ZERO) );
GE( glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE) );
cogl_rectangle (bounds_x, bounds_y, bounds_w, bounds_h);
cogl_rectangle (bounds_x, bounds_y, bounds_w, bounds_h);
GE( cogl_wrap_glDisable (GL_STENCIL_TEST) );
#else
{
/* This is our edge list it stores intersections between our curve and
* scanlines, it should probably be implemented with a data structure
* that has smaller overhead for inserting the curve/scanline intersections.
*/
GSList *scanlines[bounds_h];
GE( cogl_wrap_glDisable (GL_STENCIL_TEST) );
}
else
{
/* This is our edge list it stores intersections between our
* curve and scanlines, it should probably be implemented with a
* data structure that has smaller overhead for inserting the
* curve/scanline intersections.
*/
GSList *scanlines[bounds_h];
gint i;
gint prev_x;
gint prev_y;
gint first_x;
gint first_y;
gint lastdir=-2; /* last direction we vere moving */
gint lastline=-1; /* the previous scanline we added to */
gint i;
gint prev_x;
gint prev_y;
gint first_x;
gint first_y;
gint lastdir=-2; /* last direction we vere moving */
gint lastline=-1; /* the previous scanline we added to */
/* clear scanline intersection lists */
for (i=0; i < bounds_h; i++)
scanlines[i]=NULL;
/* clear scanline intersection lists */
for (i=0; i < bounds_h; i++)
scanlines[i]=NULL;
first_x = prev_x = CLUTTER_FIXED_TO_INT (ctx->path_nodes[0].x);
first_y = prev_y = CLUTTER_FIXED_TO_INT (ctx->path_nodes[0].y);
first_x = prev_x = CLUTTER_FIXED_TO_INT (ctx->path_nodes[0].x);
first_y = prev_y = CLUTTER_FIXED_TO_INT (ctx->path_nodes[0].y);
/* create scanline intersection list */
for (i=1; i<ctx->path_nodes_size; i++)
{
gint dest_x = CLUTTER_FIXED_TO_INT (ctx->path_nodes[i].x);
gint dest_y = CLUTTER_FIXED_TO_INT (ctx->path_nodes[i].y);
gint ydir;
gint dx;
gint dy;
gint y;
fill_close:
dx = dest_x - prev_x;
dy = dest_y - prev_y;
if (dy < 0)
ydir = -1;
else if (dy > 0)
ydir = 1;
else
ydir = 0;
/* do linear interpolation between vertexes */
for (y=prev_y; y!= dest_y; y += ydir)
{
/* only add a point if the scanline has changed and we're
* within bounds.
*/
if (y-bounds_y >= 0 &&
y-bounds_y < bounds_h &&
lastline != y)
{
gint x = prev_x + (dx * (y-prev_y)) / dy;
scanlines[ y - bounds_y ]=
g_slist_insert_sorted (scanlines[ y - bounds_y],
GINT_TO_POINTER(x),
compare_ints);
if (ydir != lastdir && /* add a double entry when changing */
lastdir!=-2) /* vertical direction */
scanlines[ y - bounds_y ]=
g_slist_insert_sorted (scanlines[ y - bounds_y],
GINT_TO_POINTER(x),
compare_ints);
lastdir = ydir;
lastline = y;
}
}
prev_x = dest_x;
prev_y = dest_y;
/* if we're on the last knot, fake the first vertex being a
next one */
if (ctx->path_nodes_size == i+1)
{
dest_x = first_x;
dest_y = first_y;
i++; /* to make the loop finally end */
goto fill_close;
}
}
/* create scanline intersection list */
for (i=1; i<ctx->path_nodes_size; i++)
{
gint dest_x = CLUTTER_FIXED_TO_INT (ctx->path_nodes[i].x);
gint dest_y = CLUTTER_FIXED_TO_INT (ctx->path_nodes[i].y);
gint ydir;
gint dx;
gint dy;
gint y;
gint spans = 0;
gint span_no;
GLfixed *coords;
fill_close:
dx = dest_x - prev_x;
dy = dest_y - prev_y;
/* count number of spans */
for (i=0; i < bounds_h; i++)
{
GSList *iter = scanlines[i];
while (iter)
{
GSList *next = iter->next;
if (!next)
{
break;
}
/* draw the segments that should be visible */
spans ++;
iter = next->next;
}
}
coords = g_malloc0 (spans * sizeof (GLfixed) * 3 * 2 * 2);
if (dy < 0)
ydir = -1;
else if (dy > 0)
ydir = 1;
else
ydir = 0;
span_no = 0;
/* build list of triangles */
for (i=0; i < bounds_h; i++)
{
GSList *iter = scanlines[i];
while (iter)
{
GSList *next = iter->next;
GLfixed x0, x1;
GLfixed y0, y1;
if (!next)
break;
/* do linear interpolation between vertexes */
for (y=prev_y; y!= dest_y; y += ydir)
{
x0 = CLUTTER_INT_TO_FIXED (GPOINTER_TO_INT (iter->data));
x1 = CLUTTER_INT_TO_FIXED (GPOINTER_TO_INT (next->data));
y0 = CLUTTER_INT_TO_FIXED (bounds_y + i);
y1 = CLUTTER_INT_TO_FIXED (bounds_y + i + 1) + 2048;
/* render scanlines 1.0625 high to avoid gaps when
transformed */
/* only add a point if the scanline has changed and we're
* within bounds.
*/
if (y-bounds_y >= 0 &&
y-bounds_y < bounds_h &&
lastline != y)
{
gint x = prev_x + (dx * (y-prev_y)) / dy;
scanlines[ y - bounds_y ]=
g_slist_insert_sorted (scanlines[ y - bounds_y],
GINT_TO_POINTER(x),
compare_ints);
if (ydir != lastdir && /* add a double entry when changing */
lastdir!=-2) /* vertical direction */
scanlines[ y - bounds_y ]=
g_slist_insert_sorted (scanlines[ y - bounds_y],
GINT_TO_POINTER(x),
compare_ints);
lastdir = ydir;
lastline = y;
}
}
prev_x = dest_x;
prev_y = dest_y;
/* if we're on the last knot, fake the first vertex being a next one */
if (ctx->path_nodes_size == i+1)
{
dest_x = first_x;
dest_y = first_y;
i++; /* to make the loop finally end */
goto fill_close;
}
}
{
gint spans = 0;
gint span_no;
GLfixed *coords;
/* count number of spans */
for (i=0; i < bounds_h; i++)
{
GSList *iter = scanlines[i];
while (iter)
{
GSList *next = iter->next;
if (!next)
{
break;
}
/* draw the segments that should be visible */
spans ++;
iter = next->next;
}
}
coords = g_malloc0 (spans * sizeof (GLfixed) * 3 * 2 * 2);
span_no = 0;
/* build list of triangles */
for (i=0; i < bounds_h; i++)
{
GSList *iter = scanlines[i];
while (iter)
{
GSList *next = iter->next;
GLfixed x0, x1;
GLfixed y0, y1;
if (!next)
break;
x0 = CLUTTER_INT_TO_FIXED (GPOINTER_TO_INT (iter->data));
x1 = CLUTTER_INT_TO_FIXED (GPOINTER_TO_INT (next->data));
y0 = CLUTTER_INT_TO_FIXED (bounds_y + i);
y1 = CLUTTER_INT_TO_FIXED (bounds_y + i + 1) + 2048;
/* render scanlines 1.0625 high to avoid gaps when transformed */
coords[span_no * 12 + 0] = x0;
coords[span_no * 12 + 1] = y0;
coords[span_no * 12 + 2] = x1;
coords[span_no * 12 + 3] = y0;
coords[span_no * 12 + 4] = x1;
coords[span_no * 12 + 5] = y1;
coords[span_no * 12 + 6] = x0;
coords[span_no * 12 + 7] = y0;
coords[span_no * 12 + 8] = x0;
coords[span_no * 12 + 9] = y1;
coords[span_no * 12 + 10] = x1;
coords[span_no * 12 + 11] = y1;
span_no ++;
iter = next->next;
}
}
for (i=0; i < bounds_h; i++)
{
g_slist_free (scanlines[i]);
}
coords[span_no * 12 + 0] = x0;
coords[span_no * 12 + 1] = y0;
coords[span_no * 12 + 2] = x1;
coords[span_no * 12 + 3] = y0;
coords[span_no * 12 + 4] = x1;
coords[span_no * 12 + 5] = y1;
coords[span_no * 12 + 6] = x0;
coords[span_no * 12 + 7] = y0;
coords[span_no * 12 + 8] = x0;
coords[span_no * 12 + 9] = y1;
coords[span_no * 12 + 10] = x1;
coords[span_no * 12 + 11] = y1;
span_no ++;
iter = next->next;
}
}
for (i=0; i < bounds_h; i++)
{
g_slist_free (scanlines[i]);
}
/* render triangles */
cogl_enable (COGL_ENABLE_VERTEX_ARRAY
| (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0));
| (ctx->color_alpha < 255 ? COGL_ENABLE_BLEND : 0));
GE ( cogl_wrap_glVertexPointer (2, GL_FIXED, 0, coords ) );
GE ( cogl_wrap_glDrawArrays (GL_TRIANGLES, 0, spans * 2 * 3));
g_free (coords);
}
}
#endif
}
}
}

View File

@ -381,7 +381,7 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
bpp = _cogl_get_format_bpp (COGL_PIXEL_FORMAT_RGBA_8888);
/* Viewport needs to have some size and be inside the window for this */
GE( glGetIntegerv (GL_VIEWPORT, viewport) );
GE( cogl_wrap_glGetIntegerv (GL_VIEWPORT, viewport) );
if (viewport[0] < 0 || viewport[1] < 0 ||
viewport[2] <= 0 || viewport[3] <= 0)
@ -422,10 +422,10 @@ _cogl_texture_download_from_gl (CoglTexture *tex,
still doesn't seem to have an alpha buffer. This might be just
a PowerVR issue.
GLint r_bits, g_bits, b_bits, a_bits;
GE( glGetIntegerv (GL_ALPHA_BITS, &a_bits) );
GE( glGetIntegerv (GL_RED_BITS, &r_bits) );
GE( glGetIntegerv (GL_GREEN_BITS, &g_bits) );
GE( glGetIntegerv (GL_BLUE_BITS, &b_bits) );
GE( cogl_wrap_glGetIntegerv (GL_ALPHA_BITS, &a_bits) );
GE( cogl_wrap_glGetIntegerv (GL_RED_BITS, &r_bits) );
GE( cogl_wrap_glGetIntegerv (GL_GREEN_BITS, &g_bits) );
GE( cogl_wrap_glGetIntegerv (GL_BLUE_BITS, &b_bits) );
printf ("R bits: %d\n", r_bits);
printf ("G bits: %d\n", g_bits);
printf ("B bits: %d\n", b_bits);

View File

@ -482,11 +482,11 @@ _cogl_features_init ()
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
GE( glGetIntegerv (GL_STENCIL_BITS, &stencil_bits) );
GE( cogl_wrap_glGetIntegerv (GL_STENCIL_BITS, &stencil_bits) );
if (stencil_bits > 0)
flags |= COGL_FEATURE_STENCIL_BUFFER;
GE( glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) );
GE( cogl_wrap_glGetIntegerv (GL_MAX_CLIP_PLANES, &max_clip_planes) );
if (max_clip_planes >= 4)
flags |= COGL_FEATURE_FOUR_CLIP_PLANES;
@ -538,13 +538,13 @@ void
cogl_get_bitmasks (gint *red, gint *green, gint *blue, gint *alpha)
{
if (red)
GE( glGetIntegerv(GL_RED_BITS, red) );
GE( cogl_wrap_glGetIntegerv(GL_RED_BITS, red) );
if (green)
GE( glGetIntegerv(GL_GREEN_BITS, green) );
GE( cogl_wrap_glGetIntegerv(GL_GREEN_BITS, green) );
if (blue)
GE( glGetIntegerv(GL_BLUE_BITS, blue) );
GE( cogl_wrap_glGetIntegerv(GL_BLUE_BITS, blue) );
if (alpha)
GE( glGetIntegerv(GL_ALPHA_BITS, alpha ) );
GE( cogl_wrap_glGetIntegerv(GL_ALPHA_BITS, alpha ) );
}
void