文档章节

eglMakeCurrent, eglSwapBuffers, glFlush, glFinish

Jerikc
 Jerikc
发布于 2016/04/14 22:12
字数 1082
阅读 265
收藏 1

I have been interested in OpenGL ES 2.0 for years and today I want to share some of my experience.

eglMakeCurrent

First of all, do you remember the function eglMakeCurrent, its prototype is:

EGLBoolean eglMakeCurrent(
    EGLDisplay display,
    EGLSurface draw,
    EGLSurface read,
    EGLContext context);

This prototype would force you to understand what are Display, Surface, and Context.


Display

As you have seen, most EGL functions require a Display as the first parameter. A Display is just a connection to the native windowing system running on your computer, like the X Window System on GNU/Linux systems, or Microsoft Windows.


Therefore, before you can use EGL functions, you must create and initialize a Display connection. This is easily done in a two-call sequence, as shown below:

EGLint majorVersion;
EGLint minorVersion;
EGLDisplay display; // EGLDisplay is just a void* type
display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (display == EGL_NO_DISPLAY)
{
    // Unable to open connection to local windowing system
}
if (!eglInitialize(display, &majorVersion, &minorVersion))
{
    // Unable to initialize EGL. Handle and recover
}

You usually (always) pass EGL_DEFAULT_DISPLAY to the function eglGetDisplay so EGL will select the default Display automatically.


Context


Context is kừn-tếch, right :) just kidding. Context is nothing but a container that contains two things:


Internal state machine (view port, depth range, clear color, textures, VBO, FBO …).

A command buffer to hold GL commands that have been called in this context.

In general, Context’s purpose is storing input data of rendering.


Surface


You can guess that Surface’s purpose is storing output of rendering. Indeed, a Surface extends a native window or pixmap with additional auxillary buffers. These buffers include a color buffer, a depth buffer, and a stencil buffer.


Back to eglMakeCurrent


So what does the function eglMakeCurrent do? If you are wondering: when I call a GL command (e.g. glDrawElements), which context and which surface is affected by that GL command; then the answer is eglMakeCurrent:

EGLBoolean eglMakeCurrent(
    EGLDisplay display,
    EGLSurface draw,
    EGLSurface read,
    EGLContext context);

eglMakeCurrent binds context to the current rendering thread AND TO the drawand read surfaces. draw is used for all GL operations except for any pixel data read back (glReadPixels, glCopyTexImage2D, and glCopyTexSubImage2D), which is taken from the frame buffer values of read.


Therefore, when you call the GL command on a thread T, OpenGL ES will detect which context C was bound to T, and which surface S[draw] and S[read] were bound to C.


Multiple contexts


Sometimes, you want to create and use more than one context. Here is the rules for that case:


Binding the same context in 2 threads is NEVER allowed.

Binding 2 different contexts in 2 different threads to the same surface is NEVER allowed.

Binding 2 different contexts in 2 different threads to 2 different surfaces MAY be allowed, but MAY fail (depending on the GPU implementation you are using).

Shared contexts


Shared contexts are useful in loading games. Because of the heavy of uploading data (especially textures) to GPU; if you want your game’s frame rate to be stable, you should run the uploading on another thread. Due to the three rules above, you must create a secondary context that uses the same internal state machine with the primary context. These primary and secondary contexts are called shared contexts.


Please note that, these two contexts share internal state machine only, they DO NOT share their command buffers.


To create the secondary context, you call:

EGLContext eglCreateContext(
EGLDisplay display,
EGLConfig config,
EGLContext share_context,
EGLint const * attrib_list);

The 3rd parameter share_context is important here, it is the primary context.


In the secondary thread, you should not draw anything, just upload data to GPU. Hence the surface that you use for this context should be a pixel buffer surface:

EGLSurface eglCreatePbufferSurface(
    EGLDisplay display,
    EGLConfig config,
    EGLint const * attrib_list);

eglSwapBuffers

EGLBoolean eglSwapBuffers(EGLDisplay display, EGLSurface surface);

At the first time I learned this function, I was thinking that its purpose is swapping the display and the surface :)) very silly.


Actually, the only thing that you need to focus here is the surface. If the surface is a pixel buffer surface, then nothing to do, the function returns without any error.


If the surface is a double-buffer surface (you often use this), the function will swap the front-buffer and the back-buffer inside the surface. The back-buffer is used to store output of rendering, while front-buffer is used by the native window to show color on your monitors.


glFlush and glFinish


The OpenGL ES driver and GPU run in a parallel/asynchronous fashion. When you call a GL command, of course, the driver will try to send the command to GPU as soon as possible for best performance. However, the command will not be immediately executed by GPU, it is just added to a queue inside GPU. Hence, if you ask the driver to send too many GL commands in a short time, the GPU queue might be full so the driver has to keep those commands in the command buffer of the current context. (Do you remember the command buffer of a context?)


That when these pending commands will be sent to the GPU is a question. In general, most OpenGL ES driver implementation may send these commands when there’s a new (next) GL command being called. But if you need the sending to be explicitly happened, please call glFlush, this will block current thread until all commands to be sent to the GPU. glFinish is more powerful, it will block current thread until all commands to be sent to GPU and completely executed by GPU. Be careful as your application’s performance will be declined.


glFlush and glFinish are called explicit synchronization. Sometimes, implicitsynchronization might be happened. That is when the eglSwapBuffers command is called. Because this command is directly executed by the driver, there’s a chance so that the GPU will draw pending glDraw* commands onto an unexpected surface buffer, since the front-buffer and back-buffer were swapped before. So, yes, as you are thinking, before swapping, the driver must block current thread to wait for all pending glDraw* commands that affect the current surface being finished.


Of course, with double-buffer surfaces, you never need to call glFlush or glFinish because eglSwapBuffers performs an implicit synchronization. But with single-buffer surfaces (i.e. in the secondary thread above), you MUST call glFlush on-time. For example, before the thread is exited, a call to glFlush is a MUST; otherwise, your GL commands might be NEVER sent to GPU.


Okay, now I can call glFinish :)


本文转载自:https://katatunix.wordpress.com/2014/09/17/lets-talk-about-eglmakecurrent-eglswapbuffers-glflush-...

Jerikc
粉丝 97
博文 246
码字总数 22757
作品 0
浦东
程序员
私信 提问
OGLplus 0.9.0 发布,OpenGL的C++封装

OGLplus 0.9.0 发布,该版本包含一些主要的改进,例如: 1. The former Uniform and ProgramUniform and VertexAttrib classes were turned to class templates. 2. The Matrix4f and Matrix......

红薯
2012/01/20
625
1
[OpenGL]环境搭建以及OpenGL初识

想往游戏行业发展的话,经常被提及到的就是OpenGL和DirectX,这两者听起来感觉是一门挺高深的技术,今天我也开始摸索学习OpenGL,那么OpenGL到底是什么?它和DirectX有什么区别和联系? Open...

蓬莱仙羽
2014/06/21
0
0
【初学者】openGL的物体转速不一样

就是如下代码里面 MyDisplay()中的第二段for循环的内容执行与否 为什么会影响第一段的物体的转速?不明白 如果把第二段for循环注释了,就会发现转速变了。。。 #include #include #include #...

Michaelwpf
2016/05/17
134
0
OpenGL超级宝典笔记——显示列表

前言 在先前的章节中,我们已经讨论OpenGL基本的一些渲染技术。这些基本的技巧足够渲染简单的图像,然而在渲染精细的画面逼真的画面的时候(非常多的顶点和纹理),如果使用之前的方式渲染(...

Mario_Q
2013/12/15
0
2
Android ,异常信息java.lang.IllegalStateException

2015-01-05-15-44-41----java.lang.IllegalStateException: eglMakeCurrent failed EGL_BAD_ALLOC at android.view.HardwareRenderer$GlRenderer.createSurface(HardwareRenderer.java:1355)......

尘世未醒
2015/01/05
2.9K
0

没有更多内容

加载失败,请刷新页面

加载更多

多线程同时加载缓存实现

import com.google.common.cache.Cache;import com.google.common.cache.CacheBuilder;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorServi......

暗中观察
23分钟前
1
0
解决Windows和Ubuntu时间不一致的问题

解决Windows和Ubuntu时间不一致的问题 问题原因是使用的时间不一致导致的。win10直接从bios读出来的时间认为就是实际时间,ubuntu认为加上8个小时 后的才是。win10用的rtc ,ubuntu用的utc 在...

shzwork
25分钟前
2
0
mysql mysql三种插入数据语句和增删改方法

点开题目是不是有点懵X,因为你只知道insert...values这一种,重来没有听说过三种,现在来介绍一下。 插入数据三种方式: insert into 表名(字段名) values(插入值); 最常用的插入语句 inse...

edison_kwok
27分钟前
2
0
利用VisualVM 内存查看

准备工作,建几个测试类。等下就是要查看这几个类里面的属性 package visualvm;public class MultiObject { private String str; private int i; MultiObject(String str...

冷基
39分钟前
1
0
组装一台工作游戏两用机

一、配置清单如下: 分类 项目 价格(元) 主板 华硕(ASUS)TUF Z370-PLUS GAMING II 电竞特工 Z370二代 支持9代CPU 1049 CPU 英特尔(Intel) i7 8700K 酷睿六核 盒装CPU处理器 2640 风扇 九...

mbzhong
45分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部