您的位置:首页 > 运维架构

OpenGL入门系列- OpenGL_ES 在 本地操作系统窗口上绘制的过程过程

2014-09-27 20:26 666 查看
EGL 是 Opengl_ES 和  本地操作系统窗口的粘合剂, 它是一种API, opengl_es和本地窗口交互就是利用的EGL。

第一步: 首先要创建本地操作系统的窗口

第二步: EGL要绑定到本地窗口,把本地窗口的类型(X11, Windows, Other)告诉EGL

第三步: 初始化EGL(EGL内部相关数据结构) 

第四步:查询窗口配置,比如窗口属性,颜色信息,深度缓存信息等。

第五步:有选择的更改一些窗口配置

第六步:创建一块可绘制区域。

第七步:创建渲染上下文(上下文一个数据结构,保存渲染状态等信息)

第八步:切换到当前的渲染上下文

第九步: 进入消息循环,渲染。

代码例子:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

//接收可变参数头文件

#include <stdarg.h>

#include <sys/time.h>

#include <GLES2/gl2.h>

#include <EGL/egl.h>

#include "esUtil.h"

#include  <X11/Xlib.h>

#include  <X11/Xatom.h>

#include  <X11/Xutil.h>

// X11 related local variables

static Display *x_display = NULL;

///

// CreateEGLContext()

//

//    Creates an EGL rendering context and all associated elements

//

EGLBoolean CreateEGLContext ( EGLNativeWindowType hWnd, EGLDisplay* eglDisplay,

                              EGLContext* eglContext, EGLSurface* eglSurface,

                              EGLint attribList[])

{

   EGLint numConfigs;

   EGLint majorVersion;

   EGLint minorVersion;

   EGLDisplay display;

   EGLContext context;

   EGLSurface surface;

   EGLConfig config;

   EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE, EGL_NONE };

   // Get Display  链接本地窗口系统,参数窗口类型

   display = eglGetDisplay((EGLNativeDisplayType)x_display);

   if ( display == EGL_NO_DISPLAY )

   {

      return EGL_FALSE;

   }

   // Initialize EGL 初始化EGL

   if ( !eglInitialize(display, &majorVersion, &minorVersion) )

   {

      return EGL_FALSE;

   }

   // Get configs 获取surface 配置

   if ( !eglGetConfigs(display, NULL, 0, &numConfigs) )

   {

      return EGL_FALSE;

   }

   // Choose config

   if ( !eglChooseConfig(display, attribList, &config, 1, &numConfigs) )

   {

      return EGL_FALSE;

   }

   // Create a surface  //创建一块区域

   surface = eglCreateWindowSurface(display, config, (EGLNativeWindowType)hWnd, NULL);

   if ( surface == EGL_NO_SURFACE )

   {

      return EGL_FALSE;

   }

   // Create a GL context //创建一个渲染上下文数据结构,保存渲染状态和相关操作

   context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs );

   if ( context == EGL_NO_CONTEXT )

   {

      return EGL_FALSE;

   }   

   

   // Make the context current

   if ( !eglMakeCurrent(display, surface, surface, context) )

   {

      return EGL_FALSE;

   }

   

   *eglDisplay = display;

   *eglSurface = surface;

   *eglContext = context;

   return EGL_TRUE;

}

///

//  WinCreate()

//

//      This function initialized the native X11 display and window for EGL

//

EGLBoolean WinCreate(ESContext *esContext, const char *title)

{

    Window root;

    XSetWindowAttributes swa;

    XSetWindowAttributes  xattr;

    Atom wm_state;

    XWMHints hints;

    XEvent xev;

    EGLConfig ecfg;

    EGLint num_config;

    Window win;

    /*

     * X11 native display initialization

     */

    x_display = XOpenDisplay(NULL);

    if ( x_display == NULL )

    {

        return EGL_FALSE;

    }

    root = DefaultRootWindow(x_display);

    swa.event_mask  =  ExposureMask | PointerMotionMask | KeyPressMask;

    win = XCreateWindow(

               x_display, root,

               0, 0, esContext->width, esContext->height, 0,

               CopyFromParent, InputOutput,

               CopyFromParent, CWEventMask,

               &swa );

    xattr.override_redirect = FALSE;

    XChangeWindowAttributes ( x_display, win, CWOverrideRedirect, &xattr );

    hints.input = TRUE;

    hints.flags = InputHint;

    XSetWMHints(x_display, win, &hints);

    // make the window visible on the screen

    XMapWindow (x_display, win);

    XStoreName (x_display, win, title);

    // get identifiers for the provided atom name strings

    wm_state = XInternAtom (x_display, "_NET_WM_STATE", FALSE);

    memset ( &xev, 0, sizeof(xev) );

    xev.type                 = ClientMessage;

    xev.xclient.window       = win;

    xev.xclient.message_type = wm_state;

    xev.xclient.format       = 32;

    xev.xclient.data.l[0]    = 1;

    xev.xclient.data.l[1]    = FALSE;

    XSendEvent (

       x_display,

       DefaultRootWindow ( x_display ),

       FALSE,

       SubstructureNotifyMask,

       &xev );

    esContext->hWnd = (EGLNativeWindowType) win;

    return EGL_TRUE;

}

///

//  userInterrupt()

//

//      Reads from X11 event loop and interrupt program if there is a keypress, or

//      window close action.

//

GLboolean userInterrupt(ESContext *esContext)

{

    XEvent xev;

    KeySym key;

    GLboolean userinterrupt = GL_FALSE;

    char text;

    // Pump all messages from X server. Keypresses are directed to keyfunc (if defined)

    while ( XPending ( x_display ) )

    {

        XNextEvent( x_display, &xev );

        if ( xev.type == KeyPress )

        {

            if (XLookupString(&xev.xkey,&text,1,&key,0)==1)

            {

                if (esContext->keyFunc != NULL)

                    esContext->keyFunc(esContext, text, 0, 0);

            }

        }

        if ( xev.type == DestroyNotify )

            userinterrupt = GL_TRUE;

    }

    return userinterrupt;

}

//////////////////////////////////////////////////////////////////

//

//  Public Functions

//

//

///

//  esInitContext()

//

//      Initialize ES utility context.  This must be called before calling any other

//      functions.

//

void ESUTIL_API esInitContext ( ESContext *esContext )

{

   if ( esContext != NULL )

   {

      memset( esContext, 0, sizeof( ESContext) );

   }

}

///

//  esCreateWindow()

//

//      title - name for title bar of window

//      width - width of window to create

//      height - height of window to create

//      flags  - bitwise or of window creation flags

//          ES_WINDOW_ALPHA       - specifies that the framebuffer should have alpha

//          ES_WINDOW_DEPTH       - specifies that a depth buffer should be created

//          ES_WINDOW_STENCIL     - specifies that a stencil buffer should be created

//          ES_WINDOW_MULTISAMPLE - specifies that a multi-sample buffer should be created

//

GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, const char* title, GLint width, GLint height, GLuint flags )

{

   EGLint attribList[] =

   {

       EGL_RED_SIZE,       5,

       EGL_GREEN_SIZE,     6,

       EGL_BLUE_SIZE,      5,

       EGL_ALPHA_SIZE,     (flags & ES_WINDOW_ALPHA) ? 8 : EGL_DONT_CARE,

       EGL_DEPTH_SIZE,     (flags & ES_WINDOW_DEPTH) ? 8 : EGL_DONT_CARE,

       EGL_STENCIL_SIZE,   (flags & ES_WINDOW_STENCIL) ? 8 : EGL_DONT_CARE,

       EGL_SAMPLE_BUFFERS, (flags & ES_WINDOW_MULTISAMPLE) ? 1 : 0,

       EGL_NONE

   };

   

   if ( esContext == NULL )

   {

      return GL_FALSE;

   }

   esContext->width = width;

   esContext->height = height;

   if ( !WinCreate ( esContext, title) )

   {

      return GL_FALSE;

   }

 

   if ( !CreateEGLContext ( esContext->hWnd,

                            &esContext->eglDisplay,

                            &esContext->eglContext,

                            &esContext->eglSurface,

                            attribList) )

   {

      return GL_FALSE;

   }

   

   return GL_TRUE;

}

///

//  esMainLoop()

//

//    Start the main loop for the OpenGL ES application

//

void ESUTIL_API esMainLoop ( ESContext *esContext )

{

    struct timeval t1, t2;

    struct timezone tz;

    float deltatime;

    float totaltime = 0.0f;

    unsigned int frames = 0;

    gettimeofday ( &t1 , &tz );

    while(userInterrupt(esContext) == GL_FALSE)

    {

        gettimeofday(&t2, &tz);

        deltatime = (float)(t2.tv_sec - t1.tv_sec + (t2.tv_usec - t1.tv_usec) * 1e-6);

        t1 = t2;

        if (esContext->updateFunc != NULL)

            esContext->updateFunc(esContext, deltatime);

        if (esContext->drawFunc != NULL)

            esContext->drawFunc(esContext);

        eglSwapBuffers(esContext->eglDisplay, esContext->eglSurface);

        totaltime += deltatime;

        frames++;

        if (totaltime >  2.0f)

        {

            printf("%4d frames rendered in %1.4f seconds -> FPS=%3.4f\n", frames, totaltime, frames/totaltime);

            totaltime -= 2.0f;

            frames = 0;

        }

    }

}

///

//  esRegisterDrawFunc()

//

void ESUTIL_API esRegisterDrawFunc ( ESContext *esContext, void (ESCALLBACK *drawFunc) (ESContext* ) )

{

   esContext->drawFunc = drawFunc;

}

///

//  esRegisterUpdateFunc()

//

void ESUTIL_API esRegisterUpdateFunc ( ESContext *esContext, void (ESCALLBACK *updateFunc) ( ESContext*, float ) )

{

   esContext->updateFunc = updateFunc;

}

///

//  esRegisterKeyFunc()

//

void ESUTIL_API esRegisterKeyFunc ( ESContext *esContext,

                                    void (ESCALLBACK *keyFunc) (ESContext*, unsigned char, int, int ) )

{

   esContext->keyFunc = keyFunc;

}

///

// esLogMessage()

//

//    Log an error message to the debug output for the platform

//

void ESUTIL_API esLogMessage ( const char *formatStr, ... )

{

    va_list params;

    char buf[BUFSIZ];

    va_start ( params, formatStr );

    vsprintf ( buf, formatStr, params );

    

    printf ( "%s", buf );

    

    va_end ( params );

}

///

// esLoadTGA()

//

//    Loads a 24-bit TGA image from a file. This is probably the simplest TGA loader ever.

//    Does not support loading of compressed TGAs nor TGAa with alpha channel. But for the

//    sake of the examples, this is sufficient.

//

char* ESUTIL_API esLoadTGA ( char *fileName, int *width, int *height )

{

    char *buffer = NULL;

    FILE *f;

    unsigned char tgaheader[12];

    unsigned char attributes[6];

    unsigned int imagesize;

    f = fopen(fileName, "rb");

    if(f == NULL) return NULL;

    if(fread(&tgaheader, sizeof(tgaheader), 1, f) == 0)

    {

        fclose(f);

        return NULL;

    }

    if(fread(attributes, sizeof(attributes), 1, f) == 0)

    {

        fclose(f);

        return 0;

    }

    *width = attributes[1] * 256 + attributes[0];

    *height = attributes[3] * 256 + attributes[2];

    imagesize = attributes[4] / 8 * *width * *height;

    buffer = malloc(imagesize);

    if (buffer == NULL)

    {

        fclose(f);

        return 0;

    }

    if(fread(buffer, 1, imagesize, f) != imagesize)

    {

        free(buffer);

        return NULL;

    }

    fclose(f);

    return buffer;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: