diff options
-rw-r--r-- | src/gles-test.c | 190 | ||||
-rw-r--r-- | src/sdl-freetype-opengles.c | 119 |
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; |