/*
 * Cogl
 *
 * An object oriented GL/GLES Abstraction/Utility Layer
 *
 * Copyright (C) 2008,2009 Intel Corporation.
 *
 * 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.
 */

#ifndef __COGL_H__
#define __COGL_H__

#include <glib.h>

#define __COGL_H_INSIDE__

#include <cogl/cogl-defines-@CLUTTER_COGL@.h>

#include <cogl/cogl-vertex-buffer.h>
#include <cogl/cogl-matrix.h>
#include <cogl/cogl-vertex-buffer.h>
#include <cogl/cogl-fixed.h>
#include <cogl/cogl-color.h>
#include <cogl/cogl-offscreen.h>
#include <cogl/cogl-material.h>
#include <cogl/cogl-path.h>
#include <cogl/cogl-shader.h>
#include <cogl/cogl-bitmap.h>
#include <cogl/cogl-texture.h>
#include <cogl/cogl-types.h>
#include <cogl/cogl-debug.h>
#include <cogl/cogl-deprecated.h>
#include <cogl/cogl-enum-types.h>

G_BEGIN_DECLS

/**
 * SECTION:cogl
 * @short_description: General purpose API
 *
 * General utility functions for COGL.
 */

/**
 * cogl_get_option_group:
 *
 * Retrieves the #GOptionGroup used by COGL to parse the command
 * line options. Clutter uses this to handle the COGL command line
 * options during its initialization process.
 *
 * Return value: a #GOptionGroup
 *
 * Since: 1.0
 */
GOptionGroup *  cogl_get_option_group         (void);

/* Misc */
/**
 * cogl_get_features:
 *
 * Returns all of the features supported by COGL.
 *
 * Return value: A logical OR of all the supported COGL features.
 *
 * Since: 0.8
 */
CoglFeatureFlags cogl_get_features         (void);

/**
 * cogl_features_available:
 * @features: A bitmask of features to check for
 *
 * Checks whether the given COGL features are available. Multiple
 * features can be checked for by or-ing them together with the '|'
 * operator. %TRUE is only returned if all of the requested features
 * are available.
 *
 * Return value: %TRUE if the features are available, %FALSE otherwise.
 */
gboolean        cogl_features_available       (CoglFeatureFlags    features);

/**
 * cogl_get_proc_address:
 * @name: the name of the function.
 *
 * Gets a pointer to a given GL or GL ES extension function. This acts
 * as a wrapper around glXGetProcAddress() or whatever is the
 * appropriate function for the current backend.
 *
 * Return value: a pointer to the requested function or %NULL if the
 * function is not available.
 */
CoglFuncPtr     cogl_get_proc_address         (const gchar        *name);

/**
 * cogl_check_extension:
 * @name: extension to check for
 * @ext: list of extensions
 *
 * Check whether @name occurs in list of extensions in @ext.
 *
 * Returns: %TRUE if the extension occurs in the list, %FALSE otherwize.
 */
gboolean        cogl_check_extension          (const gchar        *name,
                                               const gchar        *ext);

/**
 * cogl_get_bitmasks:
 * @red: Return location for the number of red bits or %NULL
 * @green: Return location for the number of green bits or %NULL
 * @blue: Return location for the number of blue bits or %NULL
 * @alpha: Return location for the number of alpha bits or %NULL
 *
 * Gets the number of bitplanes used for each of the color components
 * in the color buffer. Pass %NULL for any of the arguments if the
 * value is not required.
 */
void            cogl_get_bitmasks             (gint               *red,
                                               gint               *green,
                                               gint               *blue,
                                               gint               *alpha);

/**
 * cogl_perspective:
 * @fovy: Vertical of view angle in degrees.
 * @aspect: Aspect ratio of diesplay
 * @z_near: Nearest visible point
 * @z_far: Furthest visible point along the z-axis
 *
 * Replaces the current projection matrix with a perspective matrix
 * based on the provided values.
 */
void            cogl_perspective              (float        fovy,
                                               float        aspect,
                                               float        z_near,
                                               float        z_far);

/**
 * cogl_frustum:
 * @left: Left clipping plane
 * @right: Right clipping plane
 * @bottom: Bottom clipping plane
 * @top: Top clipping plane
 * @z_near: Nearest visible point
 * @z_far: Furthest visible point along the z-axis
 *
 * Replaces the current projection matrix with a perspective matrix
 * for the given viewing frustum.
 *
 * Since: 0.8.2
 */
void            cogl_frustum                  (float        left,
					       float        right,
					       float        bottom,
					       float        top,
                                               float        z_near,
                                               float        z_far);

/**
 * cogl_ortho:
 * @left: The coordinate for the left clipping plane
 * @right: The coordinate for the right clipping plane
 * @bottom: The coordinate for the bottom clipping plane
 * @top: The coordinate for the top clipping plane
 * @near: The coordinate for the near clipping plane (may be negative if
 *        the plane is behind the viewer)
 * @far: The coordinate for the far clipping plane (may be negative if
 *       the plane is behind the viewer)
 *
 * Replaces the current projection matrix with a parallel projection
 * matrix.
 *
 * Since: 1.0
 */
void            cogl_ortho                    (float left,
                                               float right,
                                               float bottom,
                                               float top,
                                               float near,
                                               float far);

/*
 * _cogl_setup_viewport:
 * @width: Width of the viewport
 * @height: Height of the viewport
 * @fovy: Field of view angle in degrees
 * @aspect: Aspect ratio to determine the field of view along the x-axis
 * @z_near: Nearest visible point along the z-axis
 * @z_far: Furthest visible point along the z-axis
 *
 * Replaces the current viewport and projection matrix with the given
 * values. The viewport is placed at the top left corner of the window
 * with the given width and height. The projection matrix is replaced
 * with one that has a viewing angle of @fovy along the y-axis and a
 * view scaled according to @aspect along the x-axis. The view is
 * clipped according to @z_near and @z_far on the z-axis.
 *
 * This function is used only by Clutter.
 */
void            _cogl_setup_viewport          (guint        width,
                                               guint        height,
                                               float        fovy,
                                               float        aspect,
                                               float        z_near,
                                               float        z_far);

/**
 * cogl_viewport:
 * @width: Width of the viewport
 * @height: Height of the viewport
 *
 * Replace the current viewport with the given values.
 *
 * Since: 0.8.2
 */
void            cogl_viewport                 (guint               width,
					       guint               height);

/**
 * cogl_push_matrix:
 *
 * Store the current model-view matrix on the matrix stack. The matrix
 * can later be restored with cogl_pop_matrix().
 */
void            cogl_push_matrix              (void);

/**
 * cogl_pop_matrix:
 *
 * Restore the current model-view matrix from the matrix stack.
 */
void            cogl_pop_matrix               (void);

/**
 * cogl_scale:
 * @x: Amount to scale along the x-axis
 * @y: Amount to scale along the y-axis
 * @z: Amount to scale along the z-axis
 *
 * Multiplies the current model-view matrix by one that scales the x,
 * y and z axes by the given values.
 */
void            cogl_scale                    (float        x,
                                               float        y,
                                               float        z);

/**
 * cogl_translate:
 * @x: Distance to translate along the x-axis
 * @y: Distance to translate along the y-axis
 * @z: Distance to translate along the z-axis
 *
 * Multiplies the current model-view matrix by one that translates the
 * model along all three axes according to the given values.
 */
void            cogl_translate                (float                x,
                                               float                y,
                                               float                z);

/**
 * cogl_rotate:
 * @angle: Angle in degrees to rotate.
 * @x: X-component of vertex to rotate around.
 * @y: Y-component of vertex to rotate around.
 * @z: Z-component of vertex to rotate around.
 *
 * Multiplies the current model-view matrix by one that rotates the
 * model around the vertex specified by @x, @y and @z. The rotation
 * follows the right-hand thumb rule so for example rotating by 10
 * degrees about the vertex (0, 0, 1) causes a small counter-clockwise
 * rotation.
 */
void            cogl_rotate                   (float                angle,
                                               float                x,
                                               float                y,
                                               float                z);

/**
 * cogl_get_modelview_matrix:
 * @matrix: pointer to a CoglMatrix to recieve the matrix
 *
 * Stores the current model-view matrix in @matrix.
 */
void            cogl_get_modelview_matrix     (CoglMatrix *matrix);

/**
 * cogl_set_modelview_matrix:
 * @matrix: pointer to a CoglMatrix to set as the new model-view matrix
 *
 * Loads matrix as the new model-view matrix.
 */
void            cogl_set_modelview_matrix     (CoglMatrix *matrix);

/**
 * cogl_get_projection_matrix:
 * @matrix: pointer to a CoglMatrix to recieve the matrix
 *
 * Stores the current projection matrix in @matrix.
 */
void            cogl_get_projection_matrix    (CoglMatrix *matrix);

/**
 * cogl_set_projection_matrix:
 * @matrix: pointer to a CoglMatrix to set as the new projection matrix
 *
 * Loads matrix as the new projection matrix.
 */
void            cogl_set_projection_matrix    (CoglMatrix *matrix);

/**
 * cogl_get_viewport:
 * @v: pointer to a 4 element array of #float<!-- -->s to
 * receive the viewport dimensions.
 *
 * Stores the current viewport in @v. @v[0] and @v[1] get the x and y
 * position of the viewport and @v[2] and @v[3] get the width and
 * height.
 */
void            cogl_get_viewport             (float        v[4]);

/**
 * cogl_set_depth_test_enabled:
 * @setting: %TRUE to enable depth testing or %FALSE to disable.
 *
 * Sets whether depth testing is enabled. If it is disabled then the
 * order that actors are layered on the screen depends solely on the
 * order specified using clutter_actor_raise() and
 * clutter_actor_lower(), otherwise it will also take into account the
 * actor's depth. Depth testing is disabled by default.
 */
void            cogl_set_depth_test_enabled   (gboolean setting);

/**
 * cogl_get_depth_test_enable:
 *
 * Queries if depth testing has been enabled via cogl_set_depth_test_enable()
 *
 * Returns: TRUE if depth testing is enabled else FALSE
 */
gboolean        cogl_get_depth_test_enabled   (void);

/**
 * cogl_set_backface_culling_enabled:
 * @setting: %TRUE to enable backface culling or %FALSE to disable.
 *
 * Sets whether textures positioned so that their backface is showing
 * should be hidden. This can be used to efficiently draw two-sided
 * textures or fully closed cubes without enabling depth testing. This
 * only affects calls to the cogl_rectangle* family of functions and
 * cogl_vertex_buffer_draw*. Backface culling is disabled by default.
 */
void            cogl_set_backface_culling_enabled (gboolean setting);

/**
 * cogl_get_backface_culling_enabled:
 *
 * Queries if backface culling has been enabled via
 * cogl_set_backface_culling_enabled()
 *
 * Returns: TRUE if backface culling is enabled else FALSE
 */
gboolean        cogl_get_backface_culling_enabled (void);

/**
 * cogl_set_fog:
 * @fog_color: The color of the fog
 * @mode: A CoglFogMode that determines the equation used to calculate the
 *        fogging blend factor.
 * @density: Used by the EXPONENTIAL and EXPONENTIAL_SQUARED CoglFogMode
 *           equations.
 * @z_near: Position along z-axis where no fogging should be applied
 * @z_far: Position along z-axes where full fogging should be applied
 *
 * Enables fogging. Fogging causes vertices that are further away from the eye
 * to be rendered with a different color. The color is determined according to
 * the chosen fog mode; at it's simplest the color is linearly interpolated so
 * that vertices at @z_near are drawn fully with their original color and
 * vertices at @z_far are drawn fully with @fog_color. Fogging will remain
 * enabled until you call cogl_disable_fog().
 *
 * Note: The fogging functions only work correctly when primitives use
 *       unmultiplied alpha colors. By default Cogl will premultiply textures
 *       and cogl_set_source_color will premultiply colors, so unless you
 *       explicitly load your textures requesting an unmultiplied
 *       internal_format and use cogl_material_set_color you can only use
 *       fogging with fully opaque primitives.
 *
 *       We can look to improve this in the future when we can depend on
 *       fragment shaders.
 */
void            cogl_set_fog                  (const CoglColor *fog_color,
                                               CoglFogMode      mode,
                                               float            density,
                                               float            z_near,
                                               float            z_far);

/**
 * cogl_disable_fog:
 *
 * This function disables fogging, so primitives drawn afterwards will not be
 * blended with any previously set fog color.
 */
void            cogl_disable_fog              (void);

/**
 * CoglBufferBit:
 * @COGL_BUFFER_BIT_COLOR: Selects the primary color buffer
 * @COGL_BUFFER_BIT_DEPTH: Selects the depth buffer
 * @COGL_BUFFER_BIT_STENCIL: Selects the stencil buffer
 *
 * Types of auxiliary buffers
 *
 * Since: 1.0
 */
typedef enum {
  COGL_BUFFER_BIT_COLOR   = 1L<<0,
  COGL_BUFFER_BIT_DEPTH   = 1L<<1,
  COGL_BUFFER_BIT_STENCIL = 1L<<2
} CoglBufferBit;

/**
 * cogl_clear:
 * @color: Background color to clear to
 * @buffers: A mask of #CoglBufferBit<!-- -->'s identifying which auxiliary
 *   buffers to clear
 *
 * Clears all the auxiliary buffers identified in the @buffers mask, and if
 * that includes the color buffer then the specified @color is used.
 */
void            cogl_clear                    (const CoglColor *color,
                                               gulong           buffers);

/**
 * cogl_set_source:
 * @material: A CoglMaterial object
 *
 * This function sets the source material that will be used to fill subsequent
 * geometry emitted via the cogl API.
 *
 * Note: in the future we may add the ability to set a front facing material,
 * and a back facing material, in which case this function will set both to the
 * same.
 *
 * Since 1.0
 */
void            cogl_set_source               (CoglHandle material);

/**
 * cogl_set_source_color:
 * @color: a #CoglColor
 *
 * 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.
 *
 * Since: 1.0
 */
void            cogl_set_source_color         (const CoglColor *color);

/**
 * cogl_set_source_color4ub:
 * @red: value of the red channel, between 0 and 255
 * @green: value of the green channel, between 0 and 255
 * @blue: value of the blue channel, between 0 and 255
 * @alpha: value of the alpha channel, between 0 and 255
 *
 * This is a convenience function for creating a solid fill source material
 * from the given color using unsigned bytes for each component. This
 * color will be used for any subsequent drawing operation.
 *
 * The value for each component is an unsigned byte in the range
 * between 0 and 255.
 *
 * Since: 1.0
 */
void            cogl_set_source_color4ub      (guint8 red,
                                               guint8 green,
                                               guint8 blue,
                                               guint8 alpha);

/**
 * cogl_set_source_color4f:
 * @red: value of the red channel, between 0 and %1.0
 * @green: value of the green channel, between 0 and %1.0
 * @blue: value of the blue channel, between 0 and %1.0
 * @alpha: value of the alpha channel, between 0 and %1.0
 *
 * This is a convenience function for creating a solid fill source material
 * from the given color using normalized values for each component. This color
 * will be used for any subsequent drawing operation.
 *
 * The value for each component is a fixed point number in the range
 * between 0 and %1.0. If the values passed in are outside that
 * range, they will be clamped.
 *
 * Since: 1.0
 */
void            cogl_set_source_color4f       (float red,
                                               float green,
                                               float blue,
                                               float alpha);

/**
 * cogl_set_source_texture:
 * @texture_handle: The Cogl texture you want as your source
 *
 * This is a convenience function for creating a material with the first
 * layer set to #texture_handle and setting that material as the source with
 * cogl_set_source.
 *
 * Note: There is no interaction between calls to cogl_set_source_color
 * and cogl_set_source_texture. If you need to blend a texture with a color then
 * you can create a simple material like this:
 * <programlisting>
 * material = cogl_material_new ();
 * cogl_material_set_color4ub (material, 0xff, 0x00, 0x00, 0x80);
 * cogl_material_set_layer (material, 0, tex_handle);
 * cogl_set_source (material);
 * </programlisting>
 *
 * Since 1.0
 */
void            cogl_set_source_texture       (CoglHandle texture_handle);

/**
 * SECTION:cogl-clipping
 * @short_description: Fuctions for manipulating a stack of clipping regions
 *
 * To support clipping your geometry to rectangles or paths Cogl exposes a
 * stack based API whereby each clip region you push onto the stack is
 * intersected with the previous region.
 */

/**
 * cogl_clip_push_window_rect:
 * @x_offset: left edge of the clip rectangle in window coordinates
 * @y_offset: top edge of the clip rectangle in window coordinates
 * @width: width of the clip rectangle
 * @height: height of the clip rectangle
 *
 * Specifies a rectangular clipping area for all subsequent drawing
 * operations. Any drawing commands that extend outside the rectangle
 * will be clipped so that only the portion inside the rectangle will
 * be displayed. The rectangle dimensions are not transformed by the
 * current model-view matrix.
 *
 * The rectangle is intersected with the current clip region. To undo
 * the effect of this function, call cogl_clip_pop().
 */
void            cogl_clip_push_window_rect    (float x_offset,
                                               float y_offset,
                                               float width,
                                               float height);

/**
 * cogl_clip_push:
 * @x_offset: left edge of the clip rectangle
 * @y_offset: top edge of the clip rectangle
 * @width: width of the clip rectangle
 * @height: height of the clip rectangle
 *
 * Specifies a rectangular clipping area for all subsequent drawing
 * operations. Any drawing commands that extend outside the rectangle
 * will be clipped so that only the portion inside the rectangle will
 * be displayed. The rectangle dimensions are transformed by the
 * current model-view matrix.
 *
 * The rectangle is intersected with the current clip region. To undo
 * the effect of this function, call cogl_clip_pop().
 */
void            cogl_clip_push                (float        x_offset,
                                               float        y_offset,
                                               float        width,
                                               float        height);

/**
 * cogl_clip_push_from_path:
 *
 * Sets a new clipping area using the current path. The current path
 * is then cleared. The clipping area is intersected with the previous
 * clipping area. To restore the previous clipping area, call
 * cogl_clip_pop().
 *
 * Since: 1.0
 */
void            cogl_clip_push_from_path       (void);

/**
 * cogl_clip_push_from_path_preserve:
 *
 * Sets a new clipping area using the current path. The current path
 * is then cleared. The clipping area is intersected with the previous
 * clipping area. To restore the previous clipping area, call
 * cogl_clip_pop().
 *
 * Since: 1.0
 */
void            cogl_clip_push_from_path_preserve (void);

/**
 * cogl_clip_pop:
 *
 * Reverts the clipping region to the state before the last call to
 * cogl_clip_push().
 */
void            cogl_clip_pop               (void);

/**
 * cogl_clip_ensure:
 *
 * Ensures that the current clipping region has been set in GL. This
 * will automatically be called before any Cogl primitives but it
 * maybe be neccessary to call if you are using raw GL calls with
 * clipping.
 *
 * Since: 1.0
 */
void            cogl_clip_ensure              (void);

/**
 * cogl_clip_stack_save:
 *
 * Save the entire state of the clipping stack and then clear all
 * clipping. The previous state can be returned to with
 * cogl_clip_stack_restore(). Each call to cogl_clip_push() after this
 * must be matched by a call to cogl_clip_pop() before calling
 * cogl_clip_stack_restore().
 *
 * Since: 0.8.2
 */
void            cogl_clip_stack_save          (void);

/**
 * cogl_clip_stack_restore:
 *
 * Restore the state of the clipping stack that was previously saved
 * by cogl_clip_stack_save().
 *
 * Since: 0.8.2
 */
void            cogl_clip_stack_restore       (void);

/**
 * cogl_set_draw_buffer:
 * @target: A #CoglBufferTarget that specifies what kind of draw buffer you
 *          are setting as the render target.
 * @offscreen: If you are setting a draw buffer of type COGL_OFFSCREEN_BUFFER
 *             then this is a CoglHandle for the offscreen buffer.
 *
 * This redirects all subsequent drawing to the specified draw buffer. This
 * can either be an offscreen buffer created with
 * cogl_offscreen_new_to_texture () or you can revert to your original
 * on screen window buffer.
 */
void            cogl_set_draw_buffer          (CoglBufferTarget    target,
                                               CoglHandle          offscreen);

/**
 * cogl_push_draw_buffer:
 *
 * Save cogl_set_draw_buffer() state.
 */
void            cogl_push_draw_buffer         (void);

/**
 * cogl_pop_draw_buffer:
 *
 * Restore cogl_set_draw_buffer() state.
 */
void            cogl_pop_draw_buffer          (void);


/*
 * Internal API available only to Clutter.
 *
 * These are typically only to deal with the poor seperation of
 * responsabilities that currently exists between Clutter and Cogl.
 * Eventually a lot of the backend code currently in Clutter will
 * move down into Cogl and these functions will be removed.
 */

void            _cogl_destroy_context          (void);

/* XXX: Removed before we release Clutter 1.0 since the implementation
 * wasn't complete, and so we assume no one is using this yet. Util we
 * have some one with a good usecase, we can't pretend to support breaking
 * out into raw OpenGL. */
#if 0
/*
 * cogl_flush_gl_state:
 * @flags: flags controlling what is flushed; currently unused, pass in 0
 *
 * As an optimization, COGL functions may not immediately modify GL's
 * state, instead batching up changes and applying them "just in
 * time."  Unapplied state could include glEnable() flags and the
 * current transformation matrix among other examples. If you want to
 * use GL directly, you need to flush any state COGL may have kept
 * around. cogl_flush_gl_state() syncs all of COGL's state to GL.
 *
 * Since: 1.0
 */
void            cogl_flush_gl_state         (int      flags);
#endif

/* private */
void            _cogl_set_indirect_context  (gboolean indirect);

G_END_DECLS

#undef __COGL_H_INSIDE__

#endif /* __COGL_H__ */