summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuo Jinghua <sunmoon1997@gmail.com>2011-06-10 18:03:48 +0800
committerLuo Jinghua <sunmoon1997@gmail.com>2011-06-12 09:31:52 +0800
commit4d1a3848f246666f03cef9eca095fb04d82e10b3 (patch)
tree186b3e6ed0cdeffa45c5811e1e95b87e0405980a
parentff4bd4ed3bcc3ec5c0e55c070a2de0189085dd96 (diff)
opengles: wip
-rw-r--r--src/gles-test.c190
-rw-r--r--src/sdl-freetype-opengles.c119
2 files changed, 274 insertions, 35 deletions
diff --git a/src/gles-test.c b/src/gles-test.c
new file mode 100644
index 0000000..d9c5282
--- /dev/null
+++ b/src/gles-test.c
@@ -0,0 +1,190 @@
+#include <EGL/egl.h>
+#include <GLES/gl.h>
+
+#include <sdl-freetype.h>
+#include <sdl-freetype-opengles.h>
+#include <sdl-ft.h>
+
+#include <stdio.h>
+
+static EGLDisplay eglDisplay = 0;
+static EGLConfig eglConfig = 0;
+static EGLContext eglContext = 0;
+static EGLSurface eglSurface = 0;
+static Display *x11Display = NULL;
+static Window x11Window = None;
+
+// consts
+#define COLOURDEPTH_RED_SIZE 8
+#define COLOURDEPTH_GREEN_SIZE 8
+#define COLOURDEPTH_BLUE_SIZE 8
+#define COLOURDEPTH_DEPTH_SIZE 16
+
+static const EGLint configAttribs[] ={
+ EGL_RED_SIZE, COLOURDEPTH_RED_SIZE,
+ EGL_GREEN_SIZE, COLOURDEPTH_GREEN_SIZE,
+ EGL_BLUE_SIZE, COLOURDEPTH_BLUE_SIZE,
+ EGL_DEPTH_SIZE, COLOURDEPTH_DEPTH_SIZE,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+ EGL_NONE
+};
+
+static int InitOpenGL(int width, int height)
+{
+ // use EGL to initialise GLES
+ x11Display = XOpenDisplay(NULL);
+
+ if (!x11Display)
+ {
+ fprintf(stderr, "ERROR: unable to get display!n");
+ return 0;
+ }
+
+ x11Window = XCreateSimpleWindow(x11Display,
+ RootWindow(x11Display, DefaultScreen(x11Display)),
+ 1, 1, width, height, 0,
+ BlackPixel(x11Display, DefaultScreen(x11Display)),
+ BlackPixel(x11Display, DefaultScreen(x11Display)));
+ if (x11Window == None)
+ {
+ fprintf(stderr, "ERROR: unable to create a window!n");
+ return 0;
+ }
+
+ XMapWindow(x11Display, x11Window);
+ XFlush(x11Display);
+
+ eglDisplay = eglGetDisplay((EGLNativeDisplayType)x11Display);
+ if (eglDisplay == EGL_NO_DISPLAY)
+ {
+ printf("Unable to initialise EGL display.");
+ return 0;
+ }
+
+ // Initialise egl
+ if (!eglInitialize(eglDisplay, NULL, NULL))
+ {
+ printf("Unable to initialise EGL display.");
+ return 0;
+ }
+
+ // Find a matching config
+ EGLint numConfigsOut = 0;
+ if (eglChooseConfig(eglDisplay, configAttribs, &eglConfig, 1, &numConfigsOut) != EGL_TRUE || numConfigsOut == 0)
+ {
+ fprintf(stderr, "Unable to find appropriate EGL config.");
+ return 0;
+ }
+
+ eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (EGLNativeWindowType)x11Window, 0);
+ if ( eglSurface == EGL_NO_SURFACE)
+ {
+ printf("Unable to create EGL surface!");
+ return 0;
+ }
+
+ // Bind GLES and create the context
+ eglBindAPI(EGL_OPENGL_ES_API);
+ EGLint contextParams[] = {EGL_CONTEXT_CLIENT_VERSION, 1, EGL_NONE}; // Use GLES version 1.x
+ eglContext = eglCreateContext(eglDisplay, eglConfig, NULL, NULL);
+ if (eglContext == EGL_NO_CONTEXT)
+ {
+ printf("Unable to create GLES context!");
+ return 0;
+ }
+
+ if (eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext) == EGL_FALSE)
+ {
+ printf("Unable to make GLES context current");
+ return 0;
+ }
+
+ return 1;
+}
+
+/*======================================================
+ * Kill off any opengl specific details
+ ====================================================*/
+static void TerminateOpenGL()
+{
+ eglMakeCurrent(eglDisplay, NULL, NULL, EGL_NO_CONTEXT);
+ eglDestroySurface(eglDisplay, eglSurface);
+ eglDestroyContext(eglDisplay, eglContext);
+ eglSurface = 0;
+ eglContext = 0;
+ eglConfig = 0;
+
+ eglTerminate(eglDisplay);
+ eglDisplay = 0;
+
+ XDestroyWindow(x11Display, x11Window);
+ XCloseDisplay(x11Display);
+ x11Display = NULL;
+}
+
+static int SwapBuffers()
+{
+ eglSwapBuffers(eglDisplay, eglSurface);
+}
+
+#define TEXT "sdl freetype OpenGLES render"
+
+int
+main(int argc, char *argv[])
+{
+ int done;
+ sdl_freetype_font_t * font;
+ sdl_freetype_glyph_render_t * render;
+ sdl_freetype_text_extents_t extents;
+
+ if (!InitOpenGL(640, 480))
+ return -1;
+
+ font = sdl_ft_create_font ("sans", 20,
+ SDL_FT_WEIGHT_NORMAL, SDL_FT_SLANT_NORMAL, 96);
+ if (!font)
+ goto errquit0;
+
+ render = sdl_freetype_opengles_render_create ();
+ if (!render)
+ goto errquit1;
+ sdl_freetype_font_set_render (font, render);
+
+ glMatrixMode (GL_PROJECTION) ;
+ glLoadIdentity ();
+ glOrthof (0, 640.0f, 480.0f, 0, -1.0, 1.0);
+
+ glMatrixMode (GL_MODELVIEW);
+ glLoadIdentity ();
+
+ done = 0;
+ while (!done) {
+ XEvent xevent;
+ while (XPending(x11Display)) {
+ XNextEvent(x11Display, &xevent);
+ if (xevent.type == KeyPress)
+ done = 1;
+ }
+
+ glClearColor (0.8f, 0.8f, 0.8f, 0.0f);
+ glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ sdl_freetype_font_utf8_extents (font, &extents, TEXT, -1);
+ sdl_freetype_font_show_utf8 (font, NULL, 255, 0, 0, 255,
+ (640 - extents.width) / 2 + extents.x_bearing,
+ (480 - extents.height) / 2 + extents.y_bearing,
+ TEXT, -1);
+
+ SwapBuffers();
+ usleep(10000);
+ }
+
+ errquit1:
+ sdl_freetype_font_destroy (font);
+ sdl_freetype_fini ();
+
+ errquit0:
+ TerminateOpenGL();
+ return 0;
+}
diff --git a/src/sdl-freetype-opengles.c b/src/sdl-freetype-opengles.c
index 2ce3898..b1425b5 100644
--- a/src/sdl-freetype-opengles.c
+++ b/src/sdl-freetype-opengles.c
@@ -39,12 +39,14 @@
#include <stdlib.h>
#include <stdio.h>
-#include <GL/gl.h>
+
+#include <GLES/gl.h>
#define FIXEDTOD(f) (sdl_freetype_fixed_to_double (f))
#define GLYPH_CACHE_SIZE 512
#define GLYPH_CACHE_LEVEL 64
+#define VERTEX_BUFFER_SIZE 128
typedef struct sdl_freetype_opengles_render_s {
sdl_freetype_glyph_render_t base;
@@ -56,6 +58,8 @@ typedef struct sdl_freetype_opengles_render_s {
int width, height;
float usx, usy;
GLuint texture;
+ GLfloat vertex_buffer[VERTEX_BUFFER_SIZE * 6 * 2];
+ GLfloat texcoord_buffer[VERTEX_BUFFER_SIZE * 6 * 2];
} sdl_freetype_opengles_render_t;
typedef struct {
@@ -115,8 +119,8 @@ sdl_freetype_opengles_glyph_user_data_init (sdl_freetype_font_t * font,
glGenTextures (1, &opengles_render->texture);
glBindTexture (GL_TEXTURE_2D, opengles_render->texture);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -238,15 +242,14 @@ sdl_freetype_opengles_glyph_user_data_init (sdl_freetype_font_t * font,
break;
}
- glPopClientAttrib ();
if (data)
free (data);
user_data->uv[0].x = (float)area->x;
user_data->uv[0].y = (float)area->y;
- user_data->uv[1].x = (float)(area->x + bitmap->width);
- user_data->uv[1].y = (float)(area->y + bitmap->rows);
+ user_data->uv[1].x = (float)(area->x + bitmap->width) / opengles_render->width;
+ user_data->uv[1].y = (float)(area->y + bitmap->rows) / opengles_render->height;
info->data = user_data;
return SDL_FREETYPE_ERR_OK;
}
@@ -289,6 +292,7 @@ sdl_freetype_opengles_glyphs_render (sdl_freetype_font_t * font,
sdl_freetype_glyph_info_t * info;
double x1, y1, x2, y2;
int i, num_cached;
+ GLboolean blend_enabled;
if (!render->valid) {
for (i = 0; i < num_glyphs && !render->valid; i++)
@@ -310,7 +314,7 @@ sdl_freetype_opengles_glyphs_render (sdl_freetype_font_t * font,
if (!cached)
return SDL_FREETYPE_ERR_OUT_OF_MEMORY;
- glPushAttrib (GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT);
+ blend_enabled = glIsEnabled(GL_BLEND);
num_cached = 0;
for (i = 0; i < num_glyphs; i++) {
@@ -328,10 +332,13 @@ sdl_freetype_opengles_glyphs_render (sdl_freetype_font_t * font,
}
if (num_cached) {
+ GLfloat *vertex_buffer = render->vertex_buffer;
+ GLfloat *texcoord_buffer = render->texcoord_buffer;
+ int left = num_cached;
+
glMatrixMode (GL_TEXTURE);
glPushMatrix ();
glLoadIdentity ();
- glScalef (1.0f / render->width, 1.0f / render->height, 1.0f);
glMatrixMode (GL_MODELVIEW);
glPushMatrix ();
@@ -346,37 +353,75 @@ sdl_freetype_opengles_glyphs_render (sdl_freetype_font_t * font,
glColor4ub (r, g, b, a);
- glBegin (GL_QUADS);
+ glEnableClientState (GL_VERTEX_ARRAY);
+ glEnableClientState (GL_TEXTURE_COORD_ARRAY);
- for (i = 0; i < num_cached; i++) {
- user_data = cached[i].info->data;
+ glVertexPointer (2, GL_FLOAT, 0, vertex_buffer);
+ glTexCoordPointer (2, GL_FLOAT, 0, texcoord_buffer);
- x1 = FIXEDTOD (glyphs[cached[i].index].x) + cached[i].info->x_offset;
- y2 = -FIXEDTOD (glyphs[cached[i].index].y) - cached[i].info->y_offset;
- x2 = x1 + cached[i].info->bitmap.width;
- y1 = y2 - cached[i].info->bitmap.rows;
+ i = 0;
+ while (left) {
+ int num_quads = VERTEX_BUFFER_SIZE;
+ int max_index;
+ int j = 0;
- x1 *= render->usx;
- y1 *= render->usy;
- x2 *= render->usx;
- y2 *= render->usy;
+ if (left < num_quads)
+ num_quads = left;
- glTexCoord2f (user_data->uv[0].x, user_data->uv[1].y);
- glVertex2f (x1, y1);
+ max_index = i + num_quads;
+ for (j = 0; i < max_index; i++, j += 12) {
+ user_data = cached[i].info->data;
- glTexCoord2f (user_data->uv[0].x, user_data->uv[0].y);
- glVertex2f (x1, y2);
+ x1 = FIXEDTOD (glyphs[cached[i].index].x) + cached[i].info->x_offset;
+ y2 = -FIXEDTOD (glyphs[cached[i].index].y) - cached[i].info->y_offset;
+ x2 = x1 + cached[i].info->bitmap.width;
+ y1 = y2 - cached[i].info->bitmap.rows;
- glTexCoord2f (user_data->uv[1].x, user_data->uv[0].y);
- glVertex2f (x2, y2);
+ x1 *= render->usx;
+ y1 *= render->usy;
+ x2 *= render->usx;
+ y2 *= render->usy;
- glTexCoord2f (user_data->uv[1].x, user_data->uv[1].y);
- glVertex2f (x2, y1);
+ texcoord_buffer[j + 0] = user_data->uv[0].x;
+ texcoord_buffer[j + 1] = user_data->uv[0].y;
+ vertex_buffer[j + 0] = x1;
+ vertex_buffer[j + 1] = y1;
- user_data->locked = SDL_FREETYPE_FALSE;
- }
+ texcoord_buffer[j + 2] = user_data->uv[0].x;
+ texcoord_buffer[j + 3] = user_data->uv[1].y;
+ vertex_buffer[j + 2] = x1;
+ vertex_buffer[j + 3] = y2;
+
+ texcoord_buffer[j + 4] = user_data->uv[1].x;
+ texcoord_buffer[j + 5] = user_data->uv[1].y;
+ vertex_buffer[j + 4] = x2;
+ vertex_buffer[j + 5] = y2;
+
+ texcoord_buffer[j + 6] = user_data->uv[1].x;
+ texcoord_buffer[j + 7] = user_data->uv[1].y;
+ vertex_buffer[j + 6] = x2;
+ vertex_buffer[j + 7] = y2;
+
+ texcoord_buffer[j + 8] = user_data->uv[1].x;
+ texcoord_buffer[j + 9] = user_data->uv[0].y;
+ vertex_buffer[j + 8] = x2;
+ vertex_buffer[j + 9] = y1;
- glEnd ();
+ texcoord_buffer[j + 10] = user_data->uv[0].x;
+ texcoord_buffer[j + 11] = user_data->uv[0].y;
+ vertex_buffer[j + 10] = x1;
+ vertex_buffer[j + 11] = y1;
+
+ user_data->locked = SDL_FREETYPE_FALSE;
+ }
+
+ glDrawArrays (GL_TRIANGLES, 0, num_quads * 6);
+
+ left -= num_quads;
+ }
+
+ glDisableClientState (GL_VERTEX_ARRAY);
+ glDisableClientState (GL_TEXTURE_COORD_ARRAY);
glPopMatrix ();
@@ -384,7 +429,10 @@ sdl_freetype_opengles_glyphs_render (sdl_freetype_font_t * font,
glPopMatrix ();
}
- glPopAttrib ();
+ if (!blend_enabled)
+ glDisable (GL_BLEND);
+
+ glBindTexture (GL_TEXTURE_2D, 0);
if (cached != stack_cached)
free (cached);
@@ -462,10 +510,11 @@ sdl_freetype_opengles_render_create (void)
render->subpixel = SDL_FREETYPE_FALSE;
render->usx = render->usy = 1.0;
render->width = render->height = GLYPH_CACHE_SIZE;
- render->manager = sdl_freetype_area_manager_create (render->width,
- render->height,
- GLYPH_CACHE_LEVEL,
- &sdl_freetype_opengles_glyph_ops);
+ render->manager =
+ sdl_freetype_area_manager_create (render->width,
+ render->height,
+ GLYPH_CACHE_LEVEL,
+ &sdl_freetype_opengles_glyph_ops);
if (!render->manager)
goto errquit1;