/*------------------------------------------------------------------------ * * OpenVG 1.0.1 Reference Implementation sample code * ------------------------------------------------- * * Copyright (c) 2007 The Khronos Group Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and /or associated documentation files * (the "Materials "), to deal in the Materials without restriction, * including without limitation the rights to use, copy, modify, merge, * publish, distribute, sublicense, and/or sell copies of the Materials, * and to permit persons to whom the Materials are furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Materials. * * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR * THE USE OR OTHER DEALINGS IN THE MATERIALS. * *//** * \file * \brief Tiger sample application. Resizing the application window * rerenders the tiger in the new resolution. Pressing 1,2,3 * or 4 sets pixel zoom factor, mouse moves inside the zoomed * image (mouse move works on OpenGL >= 1.2). * \note *//*-------------------------------------------------------------------*/ #include #include #include #include #include #define UNREF(X) ((void)(X)) #include #include #include #include #include #include "DejaVuSans.inc" // font data #include "DejaVuSerif.inc" #include "DejaVuSansMono.inc" #include "fontinfo.h" // font data structure #include "eglstate.h" #include "esUtil.h" #define DEBUG #ifdef DEBUG #define DBG(M, ...) printf("[FONT][%s]:" M "\n", __func__, ##__VA_ARGS__) #else #define DBG(M, ...) #endif #define GL_CHECK(x) \ x; \ { \ GLenum glError = glGetError(); \ if(glError != GL_NO_ERROR) { \ DBG("glGetError() = %i (0x%.8x) at %s:%i\n", glError, glError, __FILE__, __LINE__); \ exit(1); \ } \ } /*--------------------------------------------------------------*/ #define WINDOW_W 1024 #define WINDOW_H 768 unsigned char tgTextureBuffer [1024 * 768 * 4]; static STATE_T _state, *state = &_state; // global graphics state static const int MAXFONTPATH = 256; Fontinfo SansTypeface, SerifTypeface, MonoTypeface; //EGLDisplay egldisplay; //EGLConfig eglconfig; //EGLSurface eglsurface; //EGLContext eglcontext; VGFont font; VGPath fontpath1; VGImage fontimg1; /*--------------------------------------------------------------*/ void init(NativeWindowType window) { static const EGLint s_configAttribs[] = { EGL_SAMPLES, 4, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_ALPHA_SIZE, 0, EGL_BUFFER_SIZE, 32, //EGL_LUMINANCE_SIZE, EGL_DONT_CARE, //EGL_DONT_CARE EGL_STENCIL_SIZE, 0, EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,//EGL_OPENGL_ES2_BIT, EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_DEPTH_SIZE, 0, EGL_NONE }; EGLint numconfigs; static const EGLint contextAttributes[] = { // EGL_CONTEXT_CLIENT_VERSION, 2, /* This field will be completed according to application request. */ EGL_NONE }; static const EGLint windowAttributes[] = { //EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER, EGL_NONE /* * Uncomment and remove EGL_NONE above to specify EGL_RENDER_BUFFER value to eglCreateWindowSurface. * EGL_RENDER_BUFFER, EGL_BACK_BUFFER, * EGL_NONE */ }; state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); eglInitialize(state->display, NULL, NULL); assert(eglGetError() == EGL_SUCCESS); // eglBindAPI(EGL_OPENVG_API); eglBindAPI(EGL_OPENGL_ES_API); eglChooseConfig(state->display, s_configAttribs, &state->config, 1, &numconfigs); assert(eglGetError() == EGL_SUCCESS); assert(numconfigs == 1); state->surface = eglCreateWindowSurface(state->display, state->config, window, windowAttributes); assert(eglGetError() == EGL_SUCCESS); state->context = eglCreateContext(state->display, state->config, EGL_NO_CONTEXT, contextAttributes); assert(eglGetError() == EGL_SUCCESS); eglMakeCurrent(state->display, state->surface, state->surface, state->context); assert(eglGetError() == EGL_SUCCESS); } /*--------------------------------------------------------------*/ void deinit(void) { eglMakeCurrent(state->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); assert(eglGetError() == EGL_SUCCESS); eglTerminate(state->display); assert(eglGetError() == EGL_SUCCESS); eglReleaseThread(); } /*--------------------------------------------------------------*/ typedef struct { // Handle to a program object GLuint programObject; // Attribute locations GLint positionLoc; GLint texCoordLoc; // Sampler location GLint samplerLoc; // Texture handle GLuint textureId; float time; } UserData; // newpath creates path data VGPath newpath() { return vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0.0f, 0.0f, VG_PATH_CAPABILITY_ALL); } // Rect makes a rectangle at the specified location and dimensions void Rect(VGfloat x, VGfloat y, VGfloat w, VGfloat h) { VGPath path = newpath(); vguRect(path, x, y, w, h); vgDrawPath(path, VG_FILL_PATH); vgDrawPath(path, VG_STROKE_PATH); vgDestroyPath(path); } // setfill sets the fill color void setfill(VGfloat color[4]) { VGPaint fillPaint = vgCreatePaint(); vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); vgSetParameterfv(fillPaint, VG_PAINT_COLOR, 4, color); vgSetPaint(fillPaint, VG_FILL_PATH); vgDestroyPaint(fillPaint); } // setstroke sets the stroke color void setstroke(VGfloat color[4]) { VGPaint strokePaint = vgCreatePaint(); vgSetParameteri(strokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); vgSetParameterfv(strokePaint, VG_PAINT_COLOR, 4, color); vgSetPaint(strokePaint, VG_STROKE_PATH); vgDestroyPaint(strokePaint); } // StrokeWidth sets the stroke width void StrokeWidth(VGfloat width) { vgSetf(VG_STROKE_LINE_WIDTH, width); vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT); vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER); } // RGBA fills a color vectors from a RGBA quad. void RGBA(unsigned int r, unsigned int g, unsigned int b, VGfloat a, VGfloat color[4]) { if (r > 255) { r = 0; } if (g > 255) { g = 0; } if (b > 255) { b = 0; } if (a < 0.0 || a > 1.0) { a = 1.0; } color[0] = (VGfloat) r / 255.0f; color[1] = (VGfloat) g / 255.0f; color[2] = (VGfloat) b / 255.0f; color[3] = a; } // RGB returns a solid color from a RGB triple void RGB(unsigned int r, unsigned int g, unsigned int b, VGfloat color[4]) { RGBA(r, g, b, 1.0f, color); } // Fill sets the fillcolor, defined as a RGBA quad. void Fill(unsigned int r, unsigned int g, unsigned int b, VGfloat a) { VGfloat color[4]; RGBA(r, g, b, a, color); setfill(color); } // Ellipse makes an ellipse at the specified location and dimensions void Ellipse(VGfloat x, VGfloat y, VGfloat w, VGfloat h) { VGPath path = newpath(); vguEllipse(path, x, y, w, h); vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH); vgDestroyPath(path); } // Circle makes a circle at the specified location and dimensions void Circle(VGfloat x, VGfloat y, VGfloat r) { Ellipse(x, y, r, r); } // Text renders a string of text at a specified location, size, using the specified font glyphs // derived from http://web.archive.org/web/20070808195131/http://developer.hybrid.fi/font2openvg/renderFont.cpp.txt void Text(VGfloat x, VGfloat y, char *s, Fontinfo f, int pointsize) { VGfloat size = (VGfloat) pointsize, xx = x, mm[9]; int i; vgGetMatrix(mm); for (i = 0; i < (int)strlen(s); i++) { unsigned int character = (unsigned int)s[i]; int glyph = f.CharacterMap[character]; if (glyph == -1) { continue; //glyph is undefined } VGfloat mat[9] = { size, 0.0f, 0.0f, 0.0f, size, 0.0f, xx, y, 1.0f }; vgLoadMatrix(mm); vgMultMatrix(mat); vgDrawPath(f.Glyphs[glyph], VG_FILL_PATH); xx += size * f.GlyphAdvances[glyph] / 65536.0f; } vgLoadMatrix(mm); } // TextWidth returns the width of a text string at the specified font and size. VGfloat TextWidth(char *s, Fontinfo f, int pointsize) { int i; VGfloat tw = 0.0; VGfloat size = (VGfloat) pointsize; for (i = 0; i < (int)strlen(s); i++) { unsigned int character = (unsigned int)s[i]; int glyph = f.CharacterMap[character]; if (glyph == -1) { continue; //glyph is undefined } tw += size * f.GlyphAdvances[glyph] / 65536.0f; } return tw; } // TextMid draws text, centered on (x,y) void TextMid(VGfloat x, VGfloat y, char *s, Fontinfo f, int pointsize) { VGfloat tw = TextWidth(s, f, pointsize); Text(x - (tw / 2.0), y, s, f, pointsize); } // TextEnd draws text, with its end aligned to (x,y) void TextEnd(VGfloat x, VGfloat y, char *s, Fontinfo f, int pointsize) { VGfloat tw = TextWidth(s, f, pointsize); Text(x - tw, y, s, f, pointsize); } // Start begins the picture, clearing a rectangular region with a specified color void Start(int width, int height) { VGfloat color[4] = { 255, 255, 255, 1 }; vgSetfv(VG_CLEAR_COLOR, 4, color); vgClear(0, 0, width, height); color[0] = 0, color[1] = 0, color[2] = 0; setfill(color); setstroke(color); StrokeWidth(0); vgLoadIdentity(); } // End checks for errors, and renders to the display void End() { assert(vgGetError() == VG_NO_ERROR); eglSwapBuffers(state->display, state->surface); assert(eglGetError() == EGL_SUCCESS); } // clear the screen to a solid background color void Background(ESContext *esContext, unsigned int r, unsigned int g, unsigned int b) { Fill(r, g, b, 1); // DBG("state->screen_width = %d", state->screen_width); // DBG("state->screen_height = %d", state->screen_height); Rect(0, 0, esContext->width, esContext->height); } // clear the screen to a background color with alpha void BackgroundRGB(ESContext * esContext, unsigned int r, unsigned int g, unsigned int b, VGfloat a) { Fill(r, g, b, a); Rect(0, 0, esContext->width, esContext->height); } /*--------------------------------------------------------------*/ // // Font functions // /*--------------------------------------------------------------*/ // loadfont loads font path data // derived from http://web.archive.org/web/20070808195131/http://developer.hybrid.fi/font2openvg/renderFont.cpp.txt Fontinfo loadfont(const int *Points, const int *PointIndices, const unsigned char *Instructions, const int *InstructionIndices, const int *InstructionCounts, const int *adv, const short *cmap, int ng) { Fontinfo f; int i; memset(f.Glyphs, 0, MAXFONTPATH * sizeof(VGPath)); if (ng > MAXFONTPATH) { return f; } for (i = 0; i < ng; i++) { const int *p = &Points[PointIndices[i] * 2]; const unsigned char *instructions = &Instructions[InstructionIndices[i]]; int ic = InstructionCounts[i]; VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_S_32, // VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f / 65536.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_ALL); f.Glyphs[i] = path; if (ic) { vgAppendPathData(path, ic, instructions, p); } } f.CharacterMap = cmap; f.GlyphAdvances = adv; f.Count = ng; return f; } // unloadfont frees font path data void unloadfont(VGPath * glyphs, int n) { int i; for (i = 0; i < n; i++) { vgDestroyPath(glyphs[i]); } } void initFont() { SansTypeface = loadfont(DejaVuSans_glyphPoints, DejaVuSans_glyphPointIndices, DejaVuSans_glyphInstructions, DejaVuSans_glyphInstructionIndices, DejaVuSans_glyphInstructionCounts, DejaVuSans_glyphAdvances, DejaVuSans_characterMap, DejaVuSans_glyphCount); SerifTypeface = loadfont(DejaVuSerif_glyphPoints, DejaVuSerif_glyphPointIndices, DejaVuSerif_glyphInstructions, DejaVuSerif_glyphInstructionIndices, DejaVuSerif_glyphInstructionCounts, DejaVuSerif_glyphAdvances, DejaVuSerif_characterMap, DejaVuSerif_glyphCount); MonoTypeface = loadfont(DejaVuSansMono_glyphPoints, DejaVuSansMono_glyphPointIndices, DejaVuSansMono_glyphInstructions, DejaVuSansMono_glyphInstructionIndices, DejaVuSansMono_glyphInstructionCounts, DejaVuSansMono_glyphAdvances, DejaVuSansMono_characterMap, DejaVuSansMono_glyphCount); } void deinitFont() { unloadfont(SansTypeface.Glyphs, SansTypeface.Count); unloadfont(SerifTypeface.Glyphs, SerifTypeface.Count); unloadfont(MonoTypeface.Glyphs, MonoTypeface.Count); } /*--------------------------------------------------------------*/ GLuint CreateSimpleTexture2D( ) { // Texture object handle GLuint textureId; // 2x2 Image, 3 bytes per pixel (R, G, B) GLubyte pixels[4 * 3] = { 255, 0, 0, // Red 0, 255, 0, // Green 0, 0, 255, // Blue 255, 255, 0 // Yellow }; // Use tightly packed data glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); // Generate a texture object glGenTextures ( 1, &textureId ); // Bind the texture object glBindTexture ( GL_TEXTURE_2D, textureId ); // Load the texture glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); // Set the filtering mode glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); return textureId; } /// // Initialize the shader and program object // int Init ( ESContext *esContext ) { esContext->userData = malloc(sizeof(UserData)); UserData *userData = esContext->userData; GLbyte vShaderStr[] = "attribute vec4 a_position; \n" "attribute vec2 a_texCoord; \n" "varying vec2 v_texCoord; \n" "void main() \n" "{ \n" " gl_Position = a_position; \n" " v_texCoord = a_texCoord; \n" "} \n"; GLbyte fShaderStr[] = "precision mediump float; \n" "varying vec2 v_texCoord; \n" "uniform sampler2D s_texture; \n" "void main() \n" "{ \n" " gl_FragColor = texture2D( s_texture, v_texCoord );\n" "} \n"; // Load the shaders and get a linked program object userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); // Get the attribute locations userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); // Get the sampler location userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); // Load the texture userData->textureId = CreateSimpleTexture2D (); userData->time = 1.0f; glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); return GL_TRUE; } void Draw ( ESContext *esContext ) { UserData *userData = esContext->userData; GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0 0.0f, 0.0f, // TexCoord 0 -0.5f, -0.5f, 0.0f, // Position 1 0.0f, 1.0f, // TexCoord 1 0.5f, -0.5f, 0.0f, // Position 2 1.0f, 1.0f, // TexCoord 2 0.5f, 0.5f, 0.0f, // Position 3 1.0f, 0.0f // TexCoord 3 }; GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; VGImageFormat f; char text[] = "hello world\0"; Start(esContext->width, esContext->height); // Start the picture Background(esContext, 5, 5, 5); // Black background Fill(44, 77, 232, 1.0); // Big blue marble Circle((VGfloat) (esContext->width / 2), 0.0, (VGfloat)esContext->width); // The "world" Fill(255, 255, 255, 1.0); // White text TextMid((VGfloat)(esContext->width / 2),(VGfloat) ( esContext->height / 2),(char *) &text, SerifTypeface, esContext->width/10); // Greetings // End(); f = VG_sARGB_8888; vgReadPixels(tgTextureBuffer, esContext->width*sizeof(unsigned int), f, 0, 0, esContext->width, esContext->height); // Set the viewport glViewport ( 0, 0, esContext->width, esContext->height ); // Clear the color buffer glClear ( GL_COLOR_BUFFER_BIT ); // Use the program object glUseProgram ( userData->programObject ); // Load the vertex position glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), vVertices ); // Load the texture coordinate glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] ); glEnableVertexAttribArray ( userData->positionLoc ); glEnableVertexAttribArray ( userData->texCoordLoc ); // Bind the texture glActiveTexture ( GL_TEXTURE0 ); glBindTexture ( GL_TEXTURE_2D, userData->textureId ); // Set the sampler texture unit to 0 glUniform1i ( userData->samplerLoc, 0 ); glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); } int main ( int argc, char *argv[] ) { ESContext esContext; UserData userData; VGPath myvgPath; memset(tgTextureBuffer, 0x00, WINDOW_W * WINDOW_H * 4); esInitContext ( &esContext ); esContext.userData = &userData; DBG("Step 1. initial EGL"); esCreateWindow ( &esContext, "Simple Texture 2D", WINDOW_W, WINDOW_H, ES_WINDOW_RGB ); Init(&esContext); initFont(); esRegisterDrawFunc ( &esContext, Draw ); esMainLoop ( &esContext ); // ShutDown ( &esContext ); return 0; } #if 0 int main(void) { fbdev_window window; VGPath myvgPath; window.width= WINDOW_W; window.height= WINDOW_H; state->screen_width = window.width; state->screen_height = window.height; DBG("Step 1. initial EGL"); init((NativeWindowType)&window); // vgCreateContextMNK((VGint)window.width, (VGint)window.height, VG_RENDERING_BACKEND_TYPE_OPENGLES20); #if 1 /* font */ //font = vgCreateFont(0); //fontpath1 = vgCreatePath(VG_PATH_FORMAT_STANDARD,VG_PATH_DATATYPE_F, 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); //fontimg1 = vgCreateImage( VG_sRGBA_8888, window.width, window.height, VG_IMAGE_QUALITY_FASTER ); //vguEllipse(fontpath1, 5.0f,5.0f,5.0f,5.0f); //vgImageSubData( fontimg1, image_data, window.width*4, VG_sRGBA_8888, 0, 0, window.width, window.height); //vgSetGlyphToPath(font, 'a',fontpath1, 1, origin, escapement); //vgDestroyPath(fontpath1); //vgSetGlyphToImage(font, 'b',fontimg1, origin, escapement); //draw(window.width, window.height); //eglSwapBuffers(state->display, state->surface); initFont(); Start(state->screen_width, state->screen_height); // Start the picture Background( 0, 0, 0); // Black background Fill(44, 77, 232, 1); // Big blue marble Circle(state->screen_width / 2, 0, state->screen_width); // The "world" Fill(255, 255, 255, 1); // White text TextMid(state->screen_width / 2, state->screen_height / 2, "hello, world", SerifTypeface, state->screen_width/10); // Greetings End(); #endif deinitFont(); deinit(); return(0); } #endif