diff --git a/gles/Makefile.am b/gles/Makefile.am index 9cfc95a7d..32dda4a67 100644 --- a/gles/Makefile.am +++ b/gles/Makefile.am @@ -13,6 +13,7 @@ LDADD = $(CLUTTER_LIBS) noinst_LTLIBRARIES = libclutter-cogl.la -libclutter_cogl_la_SOURCES = \ - $(top_srcdir)/clutter/cogl/cogl.h \ +libclutter_cogl_la_SOURCES = \ + $(top_srcdir)/clutter/cogl/cogl.h \ + $(top_srcdir)/clutter/cogl/gl/cogl-defines.h \ cogl.c diff --git a/gles/cogl-defines.h b/gles/cogl-defines.h index 6354d24a7..69112a169 100644 --- a/gles/cogl-defines.h +++ b/gles/cogl-defines.h @@ -23,6 +23,8 @@ * Boston, MA 02111-1307, USA. */ +#include + #ifndef __COGL_DEFINES_H__ #define __COGL_DEFINES_H__ @@ -435,6 +437,15 @@ G_BEGIN_DECLS #define CGL_WEIGHT_ARRAY_BUFFER_BINDING_OES GL_WEIGHT_ARRAY_BUFFER_BINDING_OES #define CGL_TEXTURE_CROP_RECT_OES GL_TEXTURE_CROP_RECT_OES +typedef GLenum COGLenum; +typedef GLint COGLint; + +/* extras */ + +#define CGL_TEXTURE_2D GL_TEXTURE_2D +#define CGL_ARGB GL_ARGB +#define CGL_TEXTURE_RECTANGLE_ARB 0 /* Its unlikely we support this */ + G_END_DECLS #endif diff --git a/gles/cogl.c b/gles/cogl.c index 274d79529..470c3a45e 100644 --- a/gles/cogl.c +++ b/gles/cogl.c @@ -23,9 +23,19 @@ * Boston, MA 02111-1307, USA. */ +#include "config.h" #include "cogl.h" -#include +#include +#include + +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define PIXEL_TYPE GL_UNSIGNED_BYTE +#else +#define PIXEL_TYPE GL_UNSIGNED_INT_8_8_8_8_REV +#endif + +static gulong __enable_flags = 0; #if COGL_DEBUG struct token_string @@ -97,6 +107,10 @@ cogl_paint_init (ClutterColor *color) glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glDisable (GL_LIGHTING); glDisable (GL_DEPTH_TEST); + + cogl_enable (CGL_ENABLE_BLEND); + + glTexEnvx (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } /* FIXME: inline most of these */ @@ -113,7 +127,7 @@ cogl_pop_matrix (void) } void -cogl_scaled (ClutterFixed x, ClutterFixed y) +cogl_scale (ClutterFixed x, ClutterFixed y) { GE( glScalex (x, y, CFX_ONE) ); } @@ -144,8 +158,346 @@ cogl_rotatex (ClutterFixed angle, void cogl_rotate (gint angle, gint x, gint y, gint z) { - GE( glRotatef (CLUTTER_INT_TO_FIXED(angle), + GE( glRotatex (CLUTTER_INT_TO_FIXED(angle), CLUTTER_INT_TO_FIXED(x), CLUTTER_INT_TO_FIXED(y), CLUTTER_INT_TO_FIXED(z)) ); } + +void +cogl_enable (gulong flags) +{ + /* This function essentially caches glEnable state() in the + * hope of lessening number GL traffic. + */ + if (flags & CGL_ENABLE_BLEND) + { + if (!(__enable_flags & CGL_ENABLE_BLEND)) + { + glEnable (GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + } + __enable_flags |= CGL_ENABLE_BLEND; + } + else if (__enable_flags & CGL_ENABLE_BLEND) + { + glDisable (GL_BLEND); + __enable_flags &= ~CGL_ENABLE_BLEND; + } + + if (flags & CGL_ENABLE_TEXTURE_2D) + { + if (!(__enable_flags & CGL_ENABLE_TEXTURE_2D)) + glEnable (GL_TEXTURE_2D); + __enable_flags |= CGL_ENABLE_TEXTURE_2D; + } + else if (__enable_flags & CGL_ENABLE_TEXTURE_2D) + { + glDisable (GL_TEXTURE_2D); + __enable_flags &= ~CGL_ENABLE_TEXTURE_2D; + } + +#if 0 + if (flags & CGL_ENABLE_TEXTURE_RECT) + { + if (!(__enable_flags & CGL_ENABLE_TEXTURE_RECT)) + glEnable (GL_TEXTURE_RECTANGLE_ARB); + + __enable_flags |= CGL_ENABLE_TEXTURE_RECT; + } + else if (__enable_flags & CGL_ENABLE_TEXTURE_RECT) + { + glDisable (GL_TEXTURE_RECTANGLE_ARB); + __enable_flags &= ~CGL_ENABLE_TEXTURE_RECT; + } +#endif + + if (flags & CGL_ENABLE_ALPHA_TEST) + { + if (!(__enable_flags & CGL_ENABLE_ALPHA_TEST)) + glEnable (GL_ALPHA_TEST); + + __enable_flags |= CGL_ENABLE_ALPHA_TEST; + } + else if (__enable_flags & CGL_ENABLE_ALPHA_TEST) + { + glDisable (GL_ALPHA_TEST); + __enable_flags &= ~CGL_ENABLE_ALPHA_TEST; + } +} + +void +cogl_color (ClutterColor *color) +{ +#define FIX(x) CFX_DIV(CLUTTER_INT_TO_FIXED(x), CFX_255) + + GE( glColor4x (FIX(color->red), + FIX(color->green), + FIX(color->blue), + FIX(color->alpha)) ); +#undef FIX +} + +gboolean +cogl_texture_can_size (COGLenum pixel_format, + COGLenum pixel_type, + int width, + int height) +{ + GLint new_width = 0; + + /* FIXME */ + return TRUE; + +#if 0 + GE( glTexImage2D (GL_PROXY_TEXTURE_2D, 0, GL_RGBA, + width, height, 0 /* border */, + pixel_format, pixel_type, NULL) ); + + GE( glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, + GL_TEXTURE_WIDTH, &new_width) ); + + return new_width != 0; +#endif +} + +void +cogl_texture_quad (gint x1, + gint x2, + gint y1, + gint y2, + ClutterFixed tx1, + ClutterFixed ty1, + ClutterFixed tx2, + ClutterFixed ty2) +{ + GLfixed quadVerts[] = { + x1, y1, 0, + x2, y1, 0, + x2, y2, 0, + x2, y2, 0, + x1, y2, 0, + x1, y1, 0 + }; + + GLfixed quadTex[] = { + tx1, ty1, + tx2, ty1, + tx2, ty2, + tx2, ty2, + tx1, ty2, + tx1, ty1 + }; + + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(3, GL_FIXED, 0, quadVerts); + glTexCoordPointer(2, GL_FIXED, 0, quadTex); + + glDrawArrays(GL_TRIANGLES, 0, 6); + + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_VERTEX_ARRAY); +} + +void +cogl_textures_create (guint num, guint *textures) +{ + GE( glGenTextures (num, textures) ); +} + +void +cogl_textures_destroy (guint num, const guint *textures) +{ + GE( glDeleteTextures (num, textures) ); +} + +void +cogl_texture_bind (COGLenum target, guint texture) +{ + GE( glBindTexture (target, texture) ); +} + +void +cogl_texture_set_alignment (COGLenum target, + guint alignment, + guint row_length) +{ + /* GE( glPixelStorei (GL_UNPACK_ROW_LENGTH, row_length) ); */ + GE( glPixelStorei (GL_UNPACK_ALIGNMENT, alignment) ); +} + +void +cogl_texture_set_filters (COGLenum target, + COGLenum min_filter, + COGLenum max_filter) +{ + GE( glTexParameteri(target, GL_TEXTURE_MAG_FILTER, max_filter) ); + GE( glTexParameteri(target, GL_TEXTURE_MIN_FILTER, min_filter) ); +} + +void +cogl_texture_set_wrap (COGLenum target, + COGLenum wrap_s, + COGLenum wrap_t) +{ + GE( glTexParameteri(target, GL_TEXTURE_WRAP_S, wrap_s) ); + GE( glTexParameteri(target, GL_TEXTURE_WRAP_T, wrap_s) ); +} + +void +cogl_texture_image_2d (COGLenum target, + COGLint internal_format, + gint width, + gint height, + COGLenum format, + COGLenum type, + const guchar* pixels) +{ + GE( glTexImage2D (target, + 0, /* No mipmap support as yet */ + internal_format, + width, + height, + 0, /* 0 pixel border */ + format, + type, + pixels) ); +} + +void +cogl_texture_sub_image_2d (COGLenum target, + gint xoff, + gint yoff, + gint width, + gint height, + COGLenum format, + COGLenum type, + const guchar* pixels) +{ + GE( glTexSubImage2D (target, + 0, + xoff, + yoff, + width, + height, + format, + type, + pixels)); +} + +void +cogl_rectangle (gint x, gint y, guint width, guint height) +{ +#define FIX CLUTTER_INT_TO_FIXED + + GLfixed rect_verts[] = { + FIX(x), FIX(y), + FIX(x + width), FIX(y), + FIX(x), FIX(y + height), + FIX(x + width), FIX(y + height), + }; + +#undef FIX + + GE( glVertexPointer(2, GL_FIXED, 0, rect_verts) ); + GE( glEnableClientState(GL_VERTEX_ARRAY) ); + GE( glDrawArrays(GL_TRIANGLE_STRIP, 0, 4) ); + GE( glDisableClientState(GL_VERTEX_ARRAY) ); +} + +/* FIXME: Should use ClutterReal or Fixed */ +void +cogl_trapezoid (gint y1, + gint x11, + gint x21, + gint y2, + gint x12, + gint x22) +{ + /* FIXME */ +} + + +void +cogl_alpha_func (COGLenum func, + ClutterFixed ref) +{ + GE( glAlphaFunc (func, CLUTTER_FIXED_TO_FLOAT(ref)) ); +} + +/* + * Fixed point implementation of the perspective function + */ +void +cogl_perspective (ClutterAngle fovy, + ClutterFixed aspect, + ClutterFixed zNear, + ClutterFixed zFar) +{ + ClutterFixed xmax, ymax; + ClutterFixed x, y, c, d; + + GLfixed m[16]; + + memset (&m[0], 0, sizeof (m)); + + /* + * Based on the original algorithm in perspective(): + * + * 1) xmin = -xmax => xmax + xmin == 0 && xmax - xmin == 2 * xmax + * same true for y, hence: a == 0 && b == 0; + * + * 2) When working with small numbers, we can are loosing significant + * precision, hence we use clutter_qmulx() here, not the fast macro. + */ + ymax = clutter_qmulx (zNear, clutter_tani (fovy >> 1)); + xmax = clutter_qmulx (ymax, aspect); + + x = CFX_DIV (zNear, xmax); + y = CFX_DIV (zNear, ymax); + c = CFX_DIV (-(zFar + zNear), ( zFar - zNear)); + d = CFX_DIV (-(clutter_qmulx (2*zFar, zNear)), (zFar - zNear)); + +#define M(row,col) m[col*4+row] + M(0,0) = x; + M(1,1) = y; + M(2,2) = c; + M(2,3) = d; + M(3,2) = 1 + ~CFX_ONE; + + GE( glMultMatrixx (m) ); +#undef M +} + +void +cogl_setup_viewport (guint width, + guint height, + ClutterAngle fovy, + ClutterFixed aspect, + ClutterFixed z_near, + ClutterFixed z_far) +{ + GE( glViewport (0, 0, width, height) ); + + GE( glMatrixMode (GL_PROJECTION) ); + GE( glLoadIdentity () ); + + cogl_perspective (fovy, aspect, z_near, z_far); + + GE( glMatrixMode (GL_MODELVIEW) ); + GE( glLoadIdentity () ); + + /* camera distance from screen, 0.5 * tan (FOV) */ +#define DEFAULT_Z_CAMERA 0.866025404f + + GE( glTranslatex (-CFX_HALF, + -CFX_HALF, + -CLUTTER_FLOAT_TO_FIXED(DEFAULT_Z_CAMERA)) ); + + GE( glScalex ( CFX_DIV(CFX_ONE, CLUTTER_INT_TO_FIXED(width)), + -CFX_DIV(CFX_ONE, CLUTTER_INT_TO_FIXED(height)), + CFX_DIV(CFX_ONE, CLUTTER_INT_TO_FIXED(width))) ); + + GE( glTranslatex (0, -CFX_DIV(CFX_ONE, CLUTTER_INT_TO_FIXED(height)), 0) ); +}