struct ESContext
{
/// Put platform specific data here
void *platformData;
/// Put your user data here...
void *userData;
/// Window width
GLint width;
/// Window height
GLint height;
#ifndef __APPLE__
/// Display handle
EGLNativeDisplayType eglNativeDisplay;
/// Window handle
EGLNativeWindowType eglNativeWindow;
/// EGL display
EGLDisplay eglDisplay;
/// EGL context
EGLContext eglContext;
/// EGL surface
EGLSurface eglSurface;
#endif
/// Callbacks
void ( ESCALLBACK *drawFunc ) ( ESContext * );
void ( ESCALLBACK *shutdownFunc ) ( ESContext * );
void ( ESCALLBACK *keyFunc ) ( ESContext *, unsigned char, int, int );
void ( ESCALLBACK *updateFunc ) ( ESContext *, float deltaTime );
};
GLboolean ESUTIL_API esCreateWindow ( ESContext *esContext, const char *title, GLint width, GLint height, GLuint flags )
{
#ifndef __APPLE__
EGLConfig config;
EGLint majorVersion;
EGLint minorVersion;
EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE };
if ( esContext == NULL )
{
return GL_FALSE;
}
#ifdef ANDROID
// For Android, get the width/height from the window rather than what the
// application requested.
esContext->width = ANativeWindow_getWidth ( esContext->eglNativeWindow );
esContext->height = ANativeWindow_getHeight ( esContext->eglNativeWindow );
#else
esContext->width = width;
esContext->height = height;
#endif
if ( !WinCreate ( esContext, title ) )
{
return GL_FALSE;
}
//查询可用的显示器设备
esContext->eglDisplay = eglGetDisplay( esContext->eglNativeDisplay ); // esContext->eglNativeDisplay = EGL_DEFAULT_DISPLAY;
if ( esContext->eglDisplay == EGL_NO_DISPLAY )
{
return GL_FALSE;
}
// Initialize EGL
if ( !eglInitialize ( esContext->eglDisplay, &majorVersion, &minorVersion ) )
{
return GL_FALSE;
}
{
EGLint numConfigs = 0;
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,
// if EGL_KHR_create_context extension is supported, then we will use
// EGL_OPENGL_ES3_BIT_KHR instead of EGL_OPENGL_ES2_BIT in the attribute list
EGL_RENDERABLE_TYPE, GetContextRenderableType ( esContext->eglDisplay ),
EGL_NONE
};
// Choose config
if ( !eglChooseConfig ( esContext->eglDisplay, attribList, &config, 1, &numConfigs ) )
{
return GL_FALSE;
}
if ( numConfigs < 1 )
{
return GL_FALSE;
}
}
#ifdef ANDROID
// For Android, need to get the EGL_NATIVE_VISUAL_ID and set it using ANativeWindow_setBuffersGeometry
{
EGLint format = 0;
eglGetConfigAttrib ( esContext->eglDisplay, config, EGL_NATIVE_VISUAL_ID, &format );
ANativeWindow_setBuffersGeometry ( esContext->eglNativeWindow, 0, 0, format );
}
#endif // ANDROID
// Create a surface
esContext->eglSurface = eglCreateWindowSurface ( esContext->eglDisplay, config,
esContext->eglNativeWindow, NULL );
if ( esContext->eglSurface == EGL_NO_SURFACE )
{
return GL_FALSE;
}
// Create a GL context
esContext->eglContext = eglCreateContext ( esContext->eglDisplay, config,
EGL_NO_CONTEXT, contextAttribs );
if ( esContext->eglContext == EGL_NO_CONTEXT )
{
return GL_FALSE;
}
// Make the context current
if ( !eglMakeCurrent ( esContext->eglDisplay, esContext->eglSurface,
esContext->eglSurface, esContext->eglContext ) )
{
return GL_FALSE;
}
#endif // #ifndef __APPLE__
return GL_TRUE;
}
android创建eglwindow:
1.初始化egldisplay:
esContext->eglNativeDisplay = EGL_DEFAULT_DISPLAY;
2.根据display初始化egl,eglInitialize
3.根据EGL属性,获取opengl的配置。
4.通过config得到egl的format.
5.通过format设置buffer的格式。
6.创建eglsurface, eglCreateWindowSurface.
7.创建eglCreateContext
8.绑定eglsurface与eglcontext的绑定
1.opengl渲染方式:
OpenGl ES关于渲染方式有以下两种:
RENDERMODE_CONTINUOUSLY和RENDERMODE_WHEN_DIRTY。
默认渲染方式为RENDERMODE_CONTINUOUSLY,这两种渲染的含义是:
RENDERMODE_CONTINUOUSLY:渲染器会不停地渲染场景,
RENDERMODE_WHEN_DIRTY:只有在创建和调用requestRender()时才会刷新。
一般设置为RENDERMODE_WHEN_DIRTY方式,这样不会让CPU一直处于高速运转状态,提高手机电池使用时间和软件整体性能。
2.eclipse跟踪OPENGL:
glDisable(GL_DITHER):关闭dither
glFinish():
By doing a finish here we force the GL driver to start rendering
all the drawcalls up to this point, and to wait for the rendering to be complete
4.opengl-es:
a. 获取Display。
Display代表显示器,在有些系统上可以有多个显示器,也就会有多个Display。获得Display要调用EGLboolean eglGetDisplay(NativeDisplay dpy),参数一般为 EGL_DEFAULT_DISPLAY 。该参数实际的意义是平台实现相关的,在X-Window下是XDisplay ID,在MS Windows下是Window DC。
b. 初始化egl。
调用 EGLboolean eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor),该函数会进行一些内部初始化工作,并传回EGL版本号(major.minor)。
c. 选择Config。
所为Config实际指的是FrameBuffer的参数,在MS Windows下对应于PixelFormat,在X-Window下对应Visual。一般用EGLboolean eglChooseConfig(EGLDisplay dpy, const EGLint * attr_list, EGLConfig * config, EGLint config_size, EGLint *num_config),其中attr_list是以EGL_NONE结束的参数数组,通常以id,value依次存放,对于个别标识性的属性可以只有 id,没有value。另一个办法是用EGLboolean eglGetConfigs(EGLDisplay dpy, EGLConfig * config, EGLint config_size, EGLint *num_config) 来获得所有config。这两个函数都会返回不多于config_size个Config,结果保存在config[]中,系统的总Config个数保存 在num_config中。可以利用eglGetConfig()中间两个参数为0来查询系统支持的Config总个数。
Config有众多的Attribute,这些Attribute决定FrameBuffer的格式和能力,通过eglGetConfigAttrib ()来读取,但不能修改。
d. 构造Surface。
Surface实际上就是一个FrameBuffer,通过 EGLSurface eglCreateWindowSurface(EGLDisplay dpy, EGLConfig confg, NativeWindow win, EGLint *cfg_attr) 来创建一个可实际显示的Surface。系统通常还支持另外两种Surface:PixmapSurface和PBufferSurface,这两种都不 是可显示的Surface,PixmapSurface是保存在系统内存中的位图,PBuffer则是保存在显存中的帧。
Surface也有一些attribute,基本上都可以故名思意, EGL_HEIGHT EGL_WIDTH EGL_LARGEST_PBUFFER EGL_TEXTURE_FORMAT EGL_TEXTURE_TARGET EGL_MIPMAP_TEXTURE EGL_MIPMAP_LEVEL,通过eglSurfaceAttrib()设置、eglQuerySurface()读取。
e. 创建Context。
OpenGL的pipeline从程序的角度看就是一个状态机,有当前的颜色、纹理坐标、变换矩阵、绚染模式等一大堆状态,这些状态作用于程序提交的顶点 坐标等图元从而形成帧缓冲内的像素。在OpenGL的编程接口中,Context就代表这个状态机,程序的主要工作就是向Context提供图元、设置状 态,偶尔也从Context里获取一些信息。
用EGLContext eglCreateContext(EGLDisplay dpy, EGLSurface write, EGLSurface read, EGLContext * share_list)来创建一个Context。
f. 绘制。
应用程序通过OpenGL API进行绘制,一帧完成之后,调用eglSwapBuffers(EGLDisplay dpy, EGLContext ctx)来显示