图形渲染杂谈: 窗口、Surface、双buffer
本文以Android 为例, 全面解析native Window、Surface、Double buffer之间的关系
Native Window:
图形显示首先需要创建一个窗口 native window, 它一般与平台有关。 在Android里, ANativeWindow 这个结构体是与窗口相关的。 窗口一般会包含一个保存 显示内容的 buffer, 在Android里 这个buffer是ANativeWindow_Buffer, 是一个 结构体表示 如下:
typedef struct ANativeWindow_Buffer{
int32_t width; // 水平方向显示的像素数目
int32_t height; // 垂直方向显示的像素数目
int32_t stride; // 内存中 一行所能显示的最大 像素数目
int32_t format; // buffer中的格式
….
}ANativeWindow_Buffer;
可以看出,该buffer包含了显示一个图像时所包含的信息
结论一: WIndow实际上就是 包含了 显示图像内容的一段内存。
Surface:
这里的Surface是指 图像渲染时所需的Surface,即on-Screen Rendering Surface。
创建一个on-screen rendering surface, 首先需要创建一个本地平台的native Window:然后我们创建EGLSurface,即Surface对象:
EGLSurface eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
Config定义了颜色buffer的格式,类型和大小。
有些平台要求Widow的像素格式必须与EGLConfig定义的格式相匹配,有些平台可以要求Surface的config和Window的config不匹配,而是在需要时对它们做转换。
On-Screen Rendering Surface 可以理解为EGL创建的一个Window, 该Window与native Window不一样的地方在于,它一般会带有double buffer或者trip buffer。
结论二:On-Screen Rendering Surface实际上是从平台的设备中,一段存放图形渲染结果并与Window关联的内存。
Double-buffer:
Double-buffer可以分为front-buffer和 back-buffer, front buffer是与native window相关的buffer,也有可能直接就是native-window的ANativeWindow_buffer。
由于native-window的 ANativeWindow_buffer有自己的formats, 因此,一般在创建EGLSurface的时候会要求其config的formats与 native-window的formats相匹配。如果不匹配,那么可能需要做相应的格式转换。
back-buffer与front buffer一样,只不过他们是不同的内存地址。
Attrib_list 指定了一组与window相关的属性:如EGL_GL_COLORSPACE, EGL_RENDER_BUFFER, EGL_VG_COLORSPACE, 和 EGL_VG_ALPHA_FORMAT。
其中,EGL_RENDER_BUFFER定义了客户端渲染到window的哪个buffer里。如果其值为EGL_SINGLE_BUFFER, 那么,客户端渲染程序会直接渲染到front buffer,也就是与native window相关联的那个buffer。如果是EGL_BACK_BUFFER或者为NULL,那么就是back buffer。
如果,定义了双buffer, 那么客户端首先渲染到 back buffer,然后通过eglSwapBuffers将back buffer变换到front buffer, 这个转换过程只是一个简单的指针转换。