mutter/clutter/cogl/gl/cogl-primitives.c
Robert Bragg e82f656590 [Automatic fixed-to-float.sh change] Applies all scripted changes
This is the result of running a number of sed and perl scripts over the code to
do 90% of the work in converting from 16.16 fixed to single precision floating
point.

Note: A pristine cogl-fixed.c has been maintained as a standalone utility API
      so that applications may still take advantage of fixed point if they
      desire for certain optimisations where lower precision may be acceptable.

Note: no API changes were made in Clutter, only in Cogl.

Overview of changes:
- Within clutter/* all usage of the COGL_FIXED_ macros have been changed to use
the CLUTTER_FIXED_ macros.

- Within cogl/* all usage of the COGL_FIXED_ macros have been completly stripped
and expanded into code that works with single precision floats instead.

- Uses of cogl_fixed_* have been replaced with single precision math.h
alternatives.

- Uses of COGL_ANGLE_* and cogl_angle_* have been replaced so we use a float for
angles and math.h replacements.
2009-01-20 16:20:54 +00:00

264 lines
7.2 KiB
C

/*
* Clutter COGL
*
* A basic GL/GLES Abstraction/Utility Layer
*
* Authored By Matthew Allum <mallum@openedhand.com>
*
* Copyright (C) 2007 OpenedHand
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "cogl.h"
#include "cogl-internal.h"
#include "cogl-context.h"
#include "cogl-clip-stack.h"
#include <string.h>
#include <gmodule.h>
#define _COGL_MAX_BEZ_RECURSE_DEPTH 16
void
_cogl_rectangle (gint x,
gint y,
guint width,
guint height)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_enable (ctx->color_alpha < 255
? COGL_ENABLE_BLEND : 0);
GE( glRecti (x, y, x + width, y + height) );
}
void
_cogl_rectanglex (float x,
float y,
float width,
float height)
{
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_enable (ctx->color_alpha < 255
? COGL_ENABLE_BLEND : 0);
GE( glRectf ( (x),
(y),
(x + width),
(y + height)) );
}
void
_cogl_path_add_node (gboolean new_sub_path,
float x,
float y)
{
CoglPathNode new_node;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
new_node.x = (x);
new_node.y = (y);
new_node.path_size = 0;
if (new_sub_path || ctx->path_nodes->len == 0)
ctx->last_path = ctx->path_nodes->len;
g_array_append_val (ctx->path_nodes, new_node);
g_array_index (ctx->path_nodes, CoglPathNode, ctx->last_path).path_size++;
if (ctx->path_nodes->len == 1)
{
ctx->path_nodes_min.x = ctx->path_nodes_max.x = x;
ctx->path_nodes_min.y = ctx->path_nodes_max.y = y;
}
else
{
if (x < ctx->path_nodes_min.x) ctx->path_nodes_min.x = x;
if (x > ctx->path_nodes_max.x) ctx->path_nodes_max.x = x;
if (y < ctx->path_nodes_min.y) ctx->path_nodes_min.y = y;
if (y > ctx->path_nodes_max.y) ctx->path_nodes_max.y = y;
}
}
void
_cogl_path_stroke_nodes ()
{
guint path_start = 0;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
cogl_enable (COGL_ENABLE_VERTEX_ARRAY
| (ctx->color_alpha < 255
? COGL_ENABLE_BLEND : 0));
while (path_start < ctx->path_nodes->len)
{
CoglPathNode *path = &g_array_index (ctx->path_nodes, CoglPathNode,
path_start);
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
(guchar *) path
+ G_STRUCT_OFFSET (CoglPathNode, x)) );
GE( glDrawArrays (GL_LINE_STRIP, 0, path->path_size) );
path_start += path->path_size;
}
}
static void
_cogl_path_get_bounds (floatVec2 nodes_min,
floatVec2 nodes_max,
gint *bounds_x,
gint *bounds_y,
guint *bounds_w,
guint *bounds_h)
{
*bounds_x = floorf (nodes_min.x);
*bounds_y = floorf (nodes_min.y);
*bounds_w = ceilf (nodes_max.x
- (float)(*bounds_x));
*bounds_h = ceilf (nodes_max.y
- (float)(*bounds_y));
}
void
_cogl_add_path_to_stencil_buffer (floatVec2 nodes_min,
floatVec2 nodes_max,
guint path_size,
CoglPathNode *path,
gboolean merge)
{
guint path_start = 0;
guint sub_path_num = 0;
gint bounds_x;
gint bounds_y;
guint bounds_w;
guint bounds_h;
_cogl_path_get_bounds (nodes_min, nodes_max,
&bounds_x, &bounds_y, &bounds_w, &bounds_h);
if (merge)
{
GE( glStencilMask (2) );
GE( glStencilFunc (GL_LEQUAL, 0x2, 0x6) );
}
else
{
GE( glClear (GL_STENCIL_BUFFER_BIT) );
GE( glStencilMask (1) );
GE( glStencilFunc (GL_LEQUAL, 0x1, 0x3) );
}
GE( glEnable (GL_STENCIL_TEST) );
GE( glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT) );
GE( glColorMask (FALSE, FALSE, FALSE, FALSE) );
GE( glDepthMask (FALSE) );
while (path_start < path_size)
{
cogl_enable (COGL_ENABLE_VERTEX_ARRAY);
GE( glVertexPointer (2, GL_FLOAT, sizeof (CoglPathNode),
(guchar *) path
+ G_STRUCT_OFFSET (CoglPathNode, x)) );
GE( glDrawArrays (GL_TRIANGLE_FAN, 0, path->path_size) );
if (sub_path_num > 0)
{
/* Union the two stencil buffers bits into the least
significant bit */
GE( glStencilMask (merge ? 6 : 3) );
GE( glStencilOp (GL_ZERO, GL_REPLACE, GL_REPLACE) );
cogl_rectangle (bounds_x, bounds_y, bounds_w, bounds_h);
GE( glStencilOp (GL_INVERT, GL_INVERT, GL_INVERT) );
}
GE( glStencilMask (merge ? 4 : 2) );
path_start += path->path_size;
path += path->path_size;
sub_path_num++;
}
if (merge)
{
/* Now we have the new stencil buffer in bit 1 and the old
stencil buffer in bit 0 so we need to intersect them */
GE( glStencilMask (3) );
GE( glStencilFunc (GL_NEVER, 0x2, 0x3) );
GE( glStencilOp (GL_DECR, GL_DECR, GL_DECR) );
/* Decrement all of the bits twice so that only pixels where the
value is 3 will remain */
GE( glPushMatrix () );
GE( glLoadIdentity () );
GE( glMatrixMode (GL_PROJECTION) );
GE( glPushMatrix () );
GE( glLoadIdentity () );
GE( glRecti (-1, 1, 1, -1) );
GE( glRecti (-1, 1, 1, -1) );
GE( glPopMatrix () );
GE( glMatrixMode (GL_MODELVIEW) );
GE( glPopMatrix () );
}
GE( glStencilMask (~(GLuint) 0) );
GE( glDepthMask (TRUE) );
GE( glColorMask (TRUE, TRUE, TRUE, TRUE) );
GE( glStencilFunc (GL_EQUAL, 0x1, 0x1) );
GE( glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP) );
}
void
_cogl_path_fill_nodes ()
{
gint bounds_x;
gint bounds_y;
guint bounds_w;
guint bounds_h;
_COGL_GET_CONTEXT (ctx, NO_RETVAL);
_cogl_add_path_to_stencil_buffer (ctx->path_nodes_min,
ctx->path_nodes_max,
ctx->path_nodes->len,
&g_array_index (ctx->path_nodes,
CoglPathNode, 0),
ctx->clip.stencil_used);
_cogl_path_get_bounds (ctx->path_nodes_min, ctx->path_nodes_max,
&bounds_x, &bounds_y, &bounds_w, &bounds_h);
cogl_rectangle (bounds_x, bounds_y, bounds_w, bounds_h);
/* The stencil buffer now contains garbage so the clip area needs to
be rebuilt */
ctx->clip.stack_dirty = TRUE;
}