OpenGL/Context

Материал из Энциклопедия о программировании
Перейти к: навигация, поиск

OpenGL Context (OpenGL контекст) — дескриптор, который представляет собой много вещей: хранит все состояния, связанные с этим экземпляром OpenGL; представляет (потенциально видимый) кадровый буфер по-умолчанию, в котором будут отрисовываться команды рендеринга, когда он не рисуется в объект кадрового буфера. Думайте о контексте как об объекте, который содержит весь OpenGL; когда контекст уничтожается, OpenGL уничтожается.

Контексты локализуются в рамках определенного процесса выполнения (приложения, более или менее) в операционной системе. Процесс может создавать несколько контекстов OpenGL. Каждый контекст может представлять отдельную видимую поверхность, например окно в приложении.

Каждый контекст имеет свой собственный набор объектов OpenGL, которые не зависят от других контекстов. Объекты контекста могут использоваться совместно с другими контекстами. Большинство объектов OpenGL являются общими (предназначены для совместного использования), включая Sync Objects (объекты синхронизации) и GLSL Objects (GLSL объекты). Container Objects (контейнерные объекты) не являются ни общими, ни Query Objects (объектами запросов).

Любое совместное использование объекта должно быть сделано явно, либо при создании контекста, либо до того, как вновь созданный контекст создаст какие-либо объекты. Однако контексты не должны совместно использовать объекты; они могут оставаться полностью отделенными друг от друга.

Для работы любых команд OpenGL контекст должен быть текущим; все команды OpenGL влияют на состояние текущего контекста. Текущий контекст является локальной переменной потока, поэтому один процесс может иметь несколько потоков, каждый из которых имеет свой текущий контекст. Однако один контекст не может быть текущим в нескольких потоках одновременно.

Типы контекста

До версии 3.0 все версии OpenGL были полностью обратно совместимы с предыдущими. Код, написанный для OpenGL 1.1, может прекрасно работать в реализациях OpenGL 2.1.

В OpenGL версии 3.0 появилась идея об устаревании функциональности. Многие функции OpenGL объявлены устаревшими, что означает, что пользователям следует избегать их использования, поскольку они могут быть удалены из более поздних версий API. OpenGL 3.1 удалил почти всю функциональность, которая устарела в OpenGL 3.0. Это включает в себя конвейер с фиксированной функцией.

Однако, поскольку многие реализации в любом случае поддерживают устаревшие и удаленные функции, некоторые реализации хотят иметь возможность предоставить пользователям старших версий GL возможность получить доступ к старым API. Было опробовано несколько методик, и они попали в разделение между контекстами Core и Compatibility.

Есть и другие варианты контекста.

OpenGL 3.1 и ARB_compatibility

Новое расширение, ARB_compatibility, было представлено, когда был выпущен OpenGL 3.1. Наличие этого расширения является сигналом для пользователя, что устаревшие или удаленные функции по-прежнему доступны через исходные точки входа и перечисления. Поведение таких реализаций определяется с помощью отдельной, намного большей, спецификации OpenGL. Таким образом, была обратно-совместимая спецификация и не обратно-совместимая спецификация.

OpenGL 3.2 и профили

Когда был представлен OpenGL 3.0, также появился новый механизм создания контекста. Поскольку более поздние версии могут удалять функциональность, важно, чтобы пользователь мог запрашивать конкретную версию OpenGL, для которой он написал свой код.

Однако расширение ARB_compatibility создает проблему: реализация решает, определять его или нет. Пользователь не может запросить отключение ARB_compatibility; это было навязано ему. Это также означало, что базовая спецификация должна быть надлежащим подмножеством спецификации совместимости; спецификация ядра не может обеспечить функциональность, которую не обеспечивает совместимость.

Таким образом, еще одно изменение было внесено в создание контекста.

Форма создания контекста 3.0 не имела концепции профилей. Была только одна форма OpenGL: базовая спецификация. В 3.2 OpenGL был эффективно разделен на два профиля: ядро ​​и совместимость. Реализация требовалась только для определения ядра, поэтому совместимость не гарантируется. Однако на большинстве реализаций профиль совместимости будет доступен.

Внимание! Проблема с платформой (MacOSX): Когда MacOSX 10.7 представил поддержку OpenGL выше 2.1, они также представили дихотомию ядро/совместимость. Однако они не представили поддержку самого профиля совместимости. Вместо этого MacOSX предоставляет вам выбор: основной профиль для версий 3.2 или выше или просто версии 2.1. Нет никакого способа получить доступ к функциям после 2.1 и все еще получить доступ к конвейеру с фиксированными функциями.

Редакция 3.2 также изменила тип контекста, который может быть возвращен, позволяя давать версии 3.0 и более поздние, когда об этом прямо не спрашивают, если они поддерживают ARB_compatibility или являются профилем совместимости этой версии OpenGL. Так что если вы запрашиваете 2.1, реализация доступна, чтобы обеспечить совместимость с 3.2; это не было ранее.

Из-за изменения в формулировке способ обнаружить измененную функциональность состоит в проверке строки расширения. Если WGL_ARB_create_context_profile присутствует, то он использует редакцию 3.2. В противном случае он использует редакцию 3.0/3.1.

Прямая совместимость

Контекст версии 3.0 или выше может быть создан с установленным битом «прямой совместимости». Это приведет к тому, что для данного профиля будут удалены все функции, помеченные как «устаревшие». Вы можете объединить бит прямой совместимости с контекстами ядра и совместимости.

Для 3.0 это означает, что все устаревшие функции больше не будут доступны. Это имитирует опыт 3.1.

Для 3.1 это означает, что все оставшиеся устаревшие функциональные возможности (вещи, устаревшие в 3.0, но не удаленные в 3.1), будут удалены. В основном, широкие линии. Кроме того, вы вряд ли увидите реализации, предлагающие ARB_compatibility, если вы передадите прямую совместимость.

Для 3.2+ совместимости это вообще ничего не должно значить. Поскольку никакие функциональные возможности не помечены как устаревшие в профиле совместимости, бит прямой совместимости ничего не удаляет.

Для ядра 3.2+ это снова означает, что все функциональные возможности, которые все еще не поддерживаются (широкие линии), будут удалены.

Внимание! Рекомендация: Вы должны использовать бит прямой совместимости, только если вам нужна совместимость с MacOS. Для этого API требуется бит прямой совместимости для создания любого контекста профиля ядра.

Контексты отладки

Контекст может быть создан в режиме отладки. Это позволяет, среди прочего, функциональности отладки вывода работать более эффективно.

Нет ошибок контекстов

Можно создать контекст OpenGL, который не сообщает об ошибках OpenGL. Если бит контекста GL_CONTEXT_FLAG_NO_ERROR_BIT установлен в значение true, контекст не будет сообщать о большинстве ошибок. Он по-прежнему будет сообщать GL_OUT_OF_MEMORY_ERROR, где это уместно, но это может быть отложено с момента, когда ошибка действительно произошла. О других ошибках не сообщается.

Это также означает, что реализация также не будет проверять ошибки. Поэтому, если вы предоставите неверные параметры функции, которая вызвала ошибку, вы получите вместо этого неопределенное поведение. Это включает в себя возможность прекращения подачи заявки.

Контексты не могут иметь бит без ошибок и биты робастности или отладки.

Надежный контекст доступа

Обычно многие операции доступа к буферной памяти, которые обращаются к данным за пределами ограниченного диапазона хранилища, имеют неопределенные результаты (возможно, включая завершение программы). Однако, если программа не дает сбоя, это может привести к возможности чтения значений, записанных другими приложениями, что является проблемой безопасности.

Надежный доступ означает, что за пределами чтения чтения будут четко определены результаты (обычно ноль). И такой доступ никогда не приведет к завершению программы. Это обеспечивает лучшую изоляцию процесса.

Контекстно-информационные запросы

Существует много информации о контексте OpenGL.

Номер версии OpenGL

Чтобы получить номера старших и младших версий OpenGL, вы можете вызвать эти функции:

glGetIntegerv(GL_MAJOR_VERSION, *);
glGetIntegerv(GL_MINOR_VERSION, *);

Они доступны в контекстах OpenGL версии 3.0 и выше. Если они недоступны, вы можете использовать это вместо:

glGetString(GL_VERSION);

Возвращаемая строка начинается с «<major version>.<minor version>». После вспомогательной версии может быть другой «.», затем номер сборки, зависящий от поставщика. Строка может содержать больше контента, который полностью зависит от поставщика (поэтому не является частью стандарта OpenGL).

Например, возвращаемая строка может иметь вид «2.0.6914 WinXP SSE/SSE2/SSE3/3DNow!». 2.0 — фактический номер версии поддерживаемого GL. 6914 — это номер сборки драйвера. WinXP это ОС. SSE/SSE2/SSE3/3DNow! — это функции процессора, которые может использовать драйвер.

Иногда glGetString(GL_VERSION) также возвращает также используемый тип шины, такой как AGP или PCI или PCIEx.

Строка поставщика

С реализациями OpenGL связана строка поставщика, которая используется для идентификации создателя реализации.

glGetString(GL_VENDOR);

Это могут быть «ATI Technologies», «NVIDIA Corporation», «INTEL» и так далее. Обратите внимание, что нет гарантии, что строка для конкретного поставщика останется неизменной в будущих реализациях. В Windows, если написано «Microsoft», вы используете средство визуализации программного обеспечения Windows или оболочку Windows Direct3D. Вы, вероятно, еще не установили графические драйверы в этом случае.

Имя рендерера

Это имя рендерера, используемого реализацией.

glGetString(GL_RENDERER);

Эта строка часто является именем графического процессора. В случае Mesa3d это будет, например, «Gallium 0.4 on NVA8». Он может даже сказать «Direct3D», если используется оболочка Windows Direct3D.

Список расширений

Расширения могут быть запрошены один за другим. Для этого сначала используйте glGetIntegerv(GL_NUM_EXTENSIONS, *), чтобы получить число расширений, поддерживаемых реализацией. Затем выполните итерацию по каждому из них с этим:

glGetStringi(GL_EXTENSIONS, k);

Там, где k меньше значения GL_NUM_EXTENSIONS.

Устаревший список расширений

Внимание! Предупреждение: В этом разделе описываются устаревшие API-интерфейсы OpenGL, которые были удалены из ядра OpenGL 3.1 и более поздних версий (они устарели только в OpenGL 3.0). Рекомендуется не использовать эту функцию в своих программах.

Строка, содержащая список имен расширений, разделенных пробелами, может быть запрошена следующим образом:

glGetString(GL_EXTENSIONS);

Флаги контекста

Существует несколько видов контекстов OpenGL.

Вы можете определить, какой профиль поддерживает контекст с помощью этого запроса:

glGetIntegerv(GL_CONTEXT_PROFILE_MASK, *);

Это может содержать биты GL_CONTEXT_CORE_PROFILE_BIT или GL_CONTEXT_COMPATIBILITY_PROFILE_BIT, но не оба одновременно.

Другие особенности контекстов могут быть обнаружены с помощью флагов контекста:

glGetIntegerv(GL_CONTEXT_FLAGS, *);

Доступные контекстные флаги:

  • GL_CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT — Контекст является совместимым с контентом.
  • GL_CONTEXT_FLAG_DEBUG_BIT — Контекст является контекстом отладки.
  • GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT — Контекст поддерживает надежную функциональность доступа к памяти.
  • GL_CONTEXT_FLAG_NO_ERROR_BIT — Контекст не сообщает об ошибках OpenGL.

Языковая версия

Основная версия GLSL, поддерживаемая реализацией, может быть запрошена:

glGetString(GL_SHADING_LANGUAGE_VERSION​);

Строка версии имеет почти тот же формат, что и строка версии контекста. Разница в том, что младшая версия всегда имеет две цифры.

Поддерживаемые версии GLSL

Поддержка определенных версий GLSL может быть запрошена через индексированный get. Число поддерживаемых версий GLSL опрашивается с glGetIntegerv(GL_NUM_SHADING_LANGUAGE_VERSIONS, *). Каждая отдельная версия может быть запрошена из индексированной строки:

glGetStringi(GL_SHADING_LANGUAGE_VERSION​, k);

Где k находится на интервале от 0 до GL_NUM_SHADING_LANGUAGE_VERSIONS — 1.

Эти строки используют GLSL форматирование #version declaration. Это имеет следующие формы:

number​

или

number​ profile​

Профиль присутствует только для версий GLSL, которые имеют такое различие.

Обратите внимание, что GLSL получил объявление #version только в версии 1.10; если реализация предоставляет поддержку GLSL 1.00 (через ARB_shading_language_100), то она возвратит пустую строку ("").

Версии GLSL для OpenGL ES также могут поддерживаться. Если реализация возвращает «100», это не относится к GLSL 1.00. Вместо этого это относится к поддержке GLSL ES версии 1.00 OpenGL ES 2.0. Профиль также может быть «es», которая представляет собой версию языка шейдеров OpenGL ES. Таким образом, версия «300 es» представляет GLSL ES 3.00. GLSL ES 1.00 не использует имя профиля «es».