OpenGL ES 框架详细解析(四) —— 配置OpenGL ES的上下文

版本记录

版本号 时间
V1.0 2017.09.28

前言

OpenGL ES是一个强大的图形库,是跨平台的图形API,属于OpenGL的一个简化版本。iOS系统可以利用OpenGL ES将图像数据直接送入到GPU进行渲染,这样避免了从CPU进行计算再送到显卡渲染带来的性能的高消耗,能带来来更好的视频效果和用户体验。接下来几篇就介绍下iOS 系统的 OpenGL ES框架。感兴趣的可以看上面几篇。
1. OpenGL ES 框架详细解析(一) —— 基本概览
2. OpenGL ES 框架详细解析(二) —— 关于OpenGL ES
3. OpenGL ES 框架详细解析(三) —— 构建用于iOS的OpenGL ES应用程序的清单

配置OpenGL ES的上下文

OpenGL ES的每个实现都提供了一种创建渲染上下文来管理OpenGL ES规范所需的状态的方法。 通过将这种状态置于上下文中,多个应用程序可以轻松共享图形硬件,而不会干扰对方的状态。

下面详细介绍如何在iOS上创建和配置上下文。


EAGL Is the iOS Implementation of an OpenGL ES Rendering Context - EAGL是OpenGL ES渲染上下文的iOS实现

在您的应用程序可以调用任何OpenGL ES函数之前,必须初始化一个EAGLContext对象。 EAGLContext类还提供了用于将OpenGL ES内容与Core Animation集成的方法。


The Current Context Is the Target for OpenGL ES Function Calls - 当前上下文是OpenGL ES函数调用的目标

iOS应用程序中的每个线程都具有当前上下文; 当您调用OpenGL ES函数时,这是通过调用更改其状态的上下文。

要设置线程的当前上下文,请在该线程上执行时调用EAGLContext类方法setCurrentContext:

[EAGLContext setCurrentContext: myContext];

调用EAGLContext类方法currentContext来检索线程的当前上下文。

注意:如果您的应用程序主动在同一线程上的两个或多个上下文之间切换,请在将新上下文设置为当前上下文之前调用glFlush函数。 这样可以确保先前提交的命令及时传递给图形硬件。

OpenGL ES对与当前上下文相对应的EAGLContext对象有很强的引用。 (如果使用手动引用计数,OpenGL ES保留此对象。)当调用setCurrentContext:方法来更改当前上下文时,OpenGL ES不再引用上一个上下文。 (如果您使用手动引用计数,OpenGL ES会释放EAGLContext对象。)为防止当不在当前上下文时EAGLContext对象被释放,您的应用程序必须保持强制引用(或保留)这些对象。


Every Context Targets a Specific Version of OpenGL ES - 每个上下文都针对特定版本的OpenGL ES

EAGLContext对象只支持一个版本的OpenGL ES。 例如,为OpenGL ES 1.1编写的代码与OpenGL ES 2.03.0上下文不兼容。 使用核心OpenGL ES 2.0功能的代码与OpenGL ES 3.0上下文兼容,为OpenGL ES 2.0扩展设计的代码通常可以在OpenGL ES 3.0上下文中进行微小更改。 许多新的OpenGL ES 3.0功能和增加的硬件功能需要OpenGL ES 3.0上下文。

您的应用程序决定在创建和初始化EAGLContext对象时要支持的OpenGL ES版本。 如果设备不支持所需版本的OpenGL ES,initWithAPI:方法返回nil。 您的应用程序必须进行测试,以确保在使用上下文之前初始化成功。

为了支持多种版本的OpenGL ES作为应用程序中的渲染选项,您应该首先尝试初始化要定位的最新版本的渲染上下文。 如果返回的对象为nil,则会初始化旧版本的上下文。 下面代码演示了如何做到这一点。

//Supporting multiple versions of OpenGL ES in the same app

EAGLContext* CreateBestEAGLContext()
{
   EAGLContext *context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
   if (context == nil) {
      context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
   }
   return context;
}

上下文的API属性指出上下文支持的OpenGL ES版本。 您的应用程序应测试上下文的API属性,并使用它来选择正确的渲染路径。 实现此行为的常见模式是为每个渲染路径创建一个类。 您的应用程序在初始化时测试上下文并创建一次渲染器。


An EAGL Sharegroup Manages OpenGL ES Objects for the Context - EAGL Sharegroup 管理上下文的OpenGL ES对象

虽然上下文保持OpenGL ES状态,但它并不直接管理OpenGL ES对象。 相反,OpenGL ES对象由EAGLSharegroup对象创建和维护。 每个上下文都包含一个EAGLSharegroup对象。

当两个或多个上下文引用相同的共享组时,共享组的优点变得明显,如下图所示。 当多个上下文连接到公共共享组时,任何上下文创建的OpenGL ES对象都可用于所有上下文; 如果绑定到另一个上下文上与创建它相同的对象标识符,则引用同一个OpenGL ES对象。 移动设备上的资源通常很少; 在多个上下文中创建相同内容的多个副本是浪费的。 共享共享资源可以更好地利用设备上可用的图形资源。

一个共享组是一个不透明的对象; 它没有您的应用可以调用的方法或属性。 使用sharegroup对象的上下文保持强有力的引用。

Two contexts sharing OpenGL ES objects

在两种具体情况下,sharegroups最有用:

  • 当上下文之间共享的大部分资源是不变的。
  • 当您希望您的应用程序能够在除渲染器的主线程之外的线程上创建新的OpenGL ES对象。 在这种情况下,第二个上下文在单独的线程上运行,专门用于获取数据和创建资源。 在资源被加载之后,第一个上下文可以绑定到对象并立即使用它。 GLKTextureLoader类使用此模式提供异步纹理加载。

要创建引用同一个sharegroup的多个上下文,首先通过调用initWithAPI: 将为上下文自动创建一个共享组。 通过调用initWithAPI:sharegroup:方法,将第二个和更晚的上下文初始化为使用第一个上下文的共享组。 下面的代码显示了如何工作。 第一个上下文使用上面代码中定义的方便函数创建。 第二个上下文通过从第一个上下文中提取API版本和共享组来创建。

重要提示:与同一共享组相关联的所有上下文都必须使用与初始上下文相同的OpenGL ES API版本。

// Creating two contexts with a common sharegroup

EAGLContext* firstContext = CreateBestEAGLContext();
EAGLContext* secondContext = [[EAGLContext alloc] initWithAPI:[firstContext API] sharegroup: [firstContext sharegroup]];

当共享组由多个上下文共享时,应用程序有责任管理OpenGL ES对象的状态更改。 这是规则:

  • 如果对象未被修改,您的应用程序可以同时访问多个上下文中的对象。
  • 当通过发送到上下文的命令修改对象时,不得在任何其他上下文中读取或修改该对象。
  • 修改对象后,所有上下文都必须重新绑定对象以查看更改。 如果上下文在绑定之前引用它,则该对象的内容是未定义的。

以下是应用程序应该更新OpenGL ES对象的步骤:

  • 在可能使用对象的每个上下文上调用glFlush
  • 在要修改对象的上下文中,调用一个或多个OpenGL ES函数来更改对象。
  • 在接收到状态修改命令的上下文中调用glFlush。
  • 在其他上下文中,重新绑定对象标识符。

注意:共享对象的另一种方法是使用单个渲染上下文,但是使用多个目标帧缓冲区。 在渲染时,您的应用程序会绑定相应的帧缓冲区,并根据需要呈现其帧。 因为所有OpenGL ES对象都是从单个上下文引用的,所以它们会看到相同的OpenGL ES数据。 此模式使用的资源较少,但仅适用于可以仔细控制上下文状态的单线程应用程序。

后记

未完,待续~~~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,478评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,825评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,482评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,726评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,633评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,018评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,168评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,320评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,264评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,288评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,995评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,587评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,909评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,284评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,862评论 2 339

推荐阅读更多精彩内容