Понимание и обнаружение функциональности OpenGL
Это Техническое примечание обсуждает функциональность OpenGL, как API разработан и как разработчики могут обнаружить и получить доступ к полномочиям средства рендеринга программного обеспечения или аппаратных средств. Это запускается путем описания подразделения между базовой и расширенной функциональностью и тестом, который может использоваться для нахождения определенных функций. Продолжает описания различных версий OpenGL. Наконец, приходит к заключению с полным примером кода, что клиенты могут использовать, чтобы гарантировать, что они должным образом отслеживают и масштабируются к полному набору функций выбранного средства рендеринга.
Введение
Команды OpenGL могут быть разделены на две области, базовый API и расширения. OpenGL разработан с этим в памяти и даже если определенная команда не находится в основной спецификации, можно использовать поддерживаемое расширение для доступа к желаемой возможности. Напротив, другой 3D APIs может включать более многочисленную группу функций в их ядре, но это не гарантия поддержки GPU. Использование тех функций требует дополнительной проверки поддержки оборудования, чтобы один конец с нежелательной производительностью для команд, не имеющих поддержки оборудования в целевой системе. OpenGL гарантирует, что, если расширение будет поддерживаться в строке расширений OpenGL или через базовый API для определенного средства рендеринга, то, полную функциональность которого определенное расширение предоставлено. При взгляде на то, какая функциональность присутствует в определенной реализации, приложение должно сначала смотреть на базовую версию API для текущего средства рендеринга, затем смотреть на строку расширений..
Базовый OpenGL API
OpenGL API внутренне поддерживает определенную базовую функциональность на основе версии API. Категорическая ссылка для определенной версии является спецификацией API OpenGL, которая может быть найдена в странице спецификаций OpenGL opengl.org веб-сайта. Документация команды может также быть найдена на страницах «человека» Mac OS X и на книге «OpenGL Reference Manual».
Нахождение OpenGL версия API
OpenGL номер версии API может быть определен с помощью glGetString (GL_VERSION). Версия API основывается на возможностях средства рендеринга и является переменной на средство рендеринга. Также стоит отметить, что эта команда допустима только после того, как контекст рендеринга установлен и подключен к устройству путем присоединения drawable, потому что средство рендеринга иначе в детерминанте.
Строка версии возвращается в определенном формате с информацией об основной и вспомогательной версии, сначала сопровождаемой поставщиком определенная информация (см., что спецификация OpenGL разделяет 6.1.11). На практике требуемое пространство между этими полями может не присутствовать до Mac OS X 10.1, таким образом, разработчики должны проверить на начальную букву, числовую сопровождаемый периодом и второй числовой. Перечисление 1 показывает чтение и чистит строку версии в этой проверке случая OpenGL 1.2 или более позднюю версию API. Этот код предполагает, что контекст установлен и присоединен к drawable на рассматриваемом средстве рендеринга (это требование сохраняется для всех gl... функции).
Перечисление 1 , Находящее версию текущего средства рендеринга
#include <OpenGL/gl.h>
// get version string pointer
enum { kShortVersionLength = 32 }; // more than enough to hold the version
const GLubyte * strVersion = glGetString(GL_VERSION); // get version string
// get just the non-vendor specific part of version string
GLubyte strShortVersion [kShortVersionLength];
short i = 0;
bool fOpenGL12plus = false;
while ((((strVersion[i] <= '9') && (strVersion[i] >= '0')) ||
(strVersion[i] == '.')) && (i < kShortVersionLength))
{ // get only basic version info (until first space or not 1-9 or .)
strShortVersion [i] = strVersion[i];
i++;
}
strShortVersion [i] = 0; //truncate string
// if we are not version 1.0 or 1.1 then must be 1.2 or later
if (!strstr ((const char *) strShortVersion, "1.0") &&
!strstr ((const char *) strShortVersion, "1.1"))
fOpenGL12plus = true; |
Как только основная и вспомогательная версия убеждена, что можно искать расширенную функциональность. OpenGL предоставляет дополнительный механизм разработчикам для доступа к функциональности вне который основная спецификация посредством расширений. Немного фона на дополнительном процессе полезно в понимании проекта и функциональности и перекрытия расширений.
Расширения OpenGL
Как OpenGL расширяется API, новая функциональность обычно предоставлена посредством расширений. Они могут быть поставщиком, определенным, разных производителей, или утвержденный Architecture Review Board (ARB). Источник для получения информации о расширениях является снова страницей расширений OpenGL opengl.org веб-сайта с определенными дополнительными описаниями в Реестре Расширений OpenGL SGI. Все расширения Mac OS X детализированы в нашем руководстве по расширениям OpenGL. Обычно, расширения имеют тенденцию запускать жизнь как поставщика, определенного или разных производителей и затем перемещаться в принятие ARB или разных производителей и возможное включение в базовую спецификацию. Это не требуется, но просто продуктом инноваций и прямого прогресса с кросс-платформенным API.
Из-за этого пути принятия больше чем одно расширение может покрыть ту же основную функциональность, и средства рендеринга могут поддерживать один или больше расширений интереса. Может быть расширение ARB с той же или схожей функциональностью как поставщик определенное расширение и, как эта функциональность становится более повсеместной, это может быть перемещено в базовый OpenGL API OpenGL ARB. Как отмечено ранее, разработчики должны проверить на функциональность, желаемую и как часть базового API и как расширение, включая проверку все расширения, покрывающие желаемую функциональность. Примером этого являются операции объединителя среды текстуры, которые могут поддерживаться любой через GL_ARB_texture_env_combine или GL_EXT_texture_env_combine расширение или в ядре OpenGL 1.3, все из которых имеют очень схожую функциональность, но могут использовать различную команду и постоянный синтаксис. Так, если версия API средства рендеринга не поддерживает желаемую функциональность, исследует строку расширений, предоставленную средством рендеринга для определенного дополнительного имени, представляющего желаемую функциональность.
Наконец, в то время как существуют различные методы, которые должны быть проверены для проверки определенной функциональности, OpenGL должен продолжать экспортировать строки имени способствовавших расширений в строке расширений и продолжать поддерживать предыдущие версии расширений, экспортированных в ранних версиях Mac OS X. Таким образом никакое расширение никогда не должно удаляться из строки расширений. Это гарантирует, что разработчики в состоянии проверка на функцию с помощью текущей методологии и надежно продолжают использовать ту же методологию во всех будущих версиях Mac OS X.
Проверка расширения OpenGL
Дополнительные строки имени состоят из дополнительных имен, поддерживаемых который определенное средство рендеринга, разделенное пробелами. Строка расширений может быть длинной, и не нужно копировать ее в ограниченную длину временная строка, а скорее, проверить строку на дополнительное имя на месте. Строка имени для расширения не является именем расширений, но строкой, обозначенной полем «Name Strings» дополнительного описания. Перечисление 2 показывает пример того, как проверить строку расширений на функциональность который возможно в одном или более расширениях или версии базовой спецификации, с помощью функции удобства GLU gluCheckExtension. Отметьте, это перечисление основывается на коде, представленном в Перечислении 1.
Проверка перечисления 2 функцию OpenGL через строку расширений и номер версии
bool fTexEnvCombine = false;
// get extensions string
const GLubyte * strExtension = glGetString (GL_EXTENSIONS);
if (gluCheckExtension ("GL_ARB_texture_env_combine", strExtension) ||
gluCheckExtension ("GL_EXT_texture_env_combine", strExtension))
fTexEnvCombine = true;
// also check for API support (short version string from above)
// if we are not version 1.0, 1.1 or 1.2 then must be 1.3 or later
if (!strstr ((const char *) strShortVersion, "1.0") &&
!strstr ((const char *) strShortVersion, "1.1") &&
!strstr ((const char *) strShortVersion, "1.2"))
fTexEnvCombine = true; |
Завершить, только после успешной проверки версии API или строки расширений для определенного текущего средства рендеринга должно использование приложения желаемая команда. Как только команда, как находят, поддерживается в ядре OpenGL или в расширении для средства рендеринга в использовании, никакая дальнейшая работа не требуется. Просто включайте платформу OpenGL, «gl.h» и «glext.h» заголовочные файлы и вызовите команду по мере необходимости (нет смысла в указателях функции, требуется для Mac OS X OpenGL, но они могли использоваться в зависимости от того, какие версии ОС и функции OpenGL поддерживаются любым приложением, см. QA1188: GetProcAdress и Точки входа OpenGL для получения дополнительной информации об указателях функции).
Изменения базовой функциональности OpenGL на версию API
Так как базовая функциональность OpenGL изменилась, поскольку различные версии API были приняты, для известного удобно, какая основная функциональность была добавлена с каждой версией API. Следующий список показывает изменения в базовой функциональности в различном OpenGL версии API. Также обозначенный расширение, из которого получена функциональность. Нужно консультироваться с фактической спецификацией для получения дальнейшей информации по поводу функциональности и как это реализовано, тем более, что существуют вероятные различия между реализацией, представленной в базовом API и расширением, на котором это базируется. Дополнительная подробность о базовых изменениях API может быть найдена в 1,4 приложениях D спецификации OpenGL через F.
OpenGL 1.1
OpenGL 1.1 добавляет:
Массив вершины (GL_EXT_vertex_array)
Смещение многоугольника (GL_EXT_polygon_offset)
Логическая операция (GL_EXT_blend_logic_op)
Текстурируйте форматы изображения (GL_EXT_texture)
Среда замены текстуры (GL_EXT_texture)
Прокси текстуры (GL_EXT_texture)
Текстура копии и подтекстура (GL_EXT_copy_texture и GL_EXT_subtexture)
Объекты текстуры (GL_EXT_texture_object)
Много других незначительных изменений, обрисованных в общих чертах в разделе Appendix C 9
OpenGL 1.2
OpenGL 1.2 добавляет:
Трехмерное текстурирование (GL_EXT_texture3D)
Форматы пикселя BGRA (GL_EXT_bgra)
Упакованные форматы пикселя (GL_EXT_packed_pixels)
Нормальное перемасштабирование (GL_EXT_rescale_normal)
Разделите зеркальный цвет (GL_EXT_separate_specular_color)
Край координаты текстуры, фиксирующий (GL_SGIS_texture_edge_clamp)
Текстурируйте управление уровнем детализации (GL_SGIS_texture_lod)
Массив вершины рисует диапазон элемента (GL_EXT_draw_range_elements)
Отображая Подмножество (GL_SGI_color_table, GL_EXT_color_subtable, GL_EXT_convolution, GL_HP_convolution_border_modes, GL_SGI_color_matrix, GL_EXT_histogram, GL_EXT_blend_color, GL_EXT_blend_minmax и GL_EXT_blend_subtract; Отметьте, может не присутствовать на всех реализациях, должен быть проверенным путем проверки на расширение ARB_imaging),
OpenGL 1.2.1
OpenGL 1.2.1 представил расширения ARB без определенных базовых изменений API.
OpenGL 1.3
OpenGL 1.3 добавляет:
Сжатые текстуры (GL_ARB_texture_compression)
Текстуры карты куба (GL_ARB_texture_cube_map)
Мультивыборка (GL_ARB_multisample)
Мультитекстура (GL_ARB_multitexture)
Текстура добавляет режим среды (GL_ARB_texture_env_add)
Режим среды объединения текстуры
(GL_ARB_texture_env_combine) Текстурируйте режим среды Dot3 (GL_ARB_texture_env_dot3)
Зажим границы текстуры (GL_ARB_texture_border_clamp)
Переместите матрицу (GL_ARB_transpose_matrix)
OpenGL 1.4
OpenGL 1.4 добавляет:
Автоматическая генерация множественного отображения (GL_SGIS_generate_mipmap)
Смешение, придающее (GL_NV_blend_square) квадратную форму
Текстуры глубины (GL_ARB_depth_texture)
Тени (GL_ARB_shadow)
Координата вуали (GL_EXT_fog_coord)
Многократные массивы получения (GL_EXT_multi_draw_arrays)
Параметры точки (GL_ARB_point_parameters)
Дополнительный цвет (GL_EXT_secondary_color)
Отдельные функции смешения (GL_EXT_blend_func_separate)
Обертка шаблона (GL_EXT_stencil_wrap)
Текстурируйте перекрестный режим среды (GL_ARB_texture_env_crossbar)
Текстурируйте смещение ЛОДА (GL_EXT_texture_lod_bias)
Текстурируйте зеркальное повторение (GL_ARB_texture_mirrored_repeat)
Растровая позиция окна (GL_ARB_window_pos)
OpenGL 1.5
OpenGL 1.5 добавляет:
Буферные объекты (GL_ARB_vertex_buffer_object)
Запросы поглощения газов (GL_ARB_occlusion_query)
Теневые функции (GL_EXT_shadow_funcs)
Функциональность выше требуется, чтобы присутствовать, если средство рендеринга сообщает об определенной версии независимо от того, какие расширения поддерживаются. Снова, стоит отметить, что средства рендеринга могут или могут не поддерживать расширения, которые базируется функциональность API. Например, если средство рендеринга сообщает о версии 1.3, оно может или может не поддерживать GL_ARB_texture_env_combine или GL_EXT_texture_env_combine расширения, хотя функциональность это расширение представляет, будут доступны через базовые 1,3 API.
Нахождение допустимого средства рендеринга для проверки функциональности
Как обсуждено ранее, проверение функциональности требует, чтобы средство рендеринга, присоединенное к drawable для команд OpenGL, возвратило допустимые результаты. Когда не drawable присоединенные команды OpenGL, эффективно «без OPs», таким образом возвращают недопустимые результаты. Существует пара различных методов для обеспечения допустимой среды рендеринга. Во-первых, можно создать формат пикселя, и контекст тогда присоединяют это к допустимому drawable для OS API в использовании, таком как окно, представление или экран. Так как средства рендеринга могут измениться с включением изменений дисплея, нужно также гарантировать, что используемое drawable правильно расположено на дисплей интереса (или выполните итерации через набор дисплеев интереса). В то время как, нет никакого требования для создания drawable видимого, позволяющего этому действию иметь место, не тревожа пользователя, было бы желательно иметь метод, не включающий создание drawable и который мог использоваться любым OS API (CGL, NSOpenGL или AGL).
Перечисление 3 показывает метод с помощью CGL, который доступен любому Мужественному приложению, для определения возможностей средства рендеринга на основе дисплея, даже если то приложение использует NSOpenGL или недостаток AGL CGL для его интерфейса к OpenGL. Этот код не создает drawable, но вместо этого использует маску дисплея OpenGL в формате пикселя для ограничения формата пикселя и таким образом контекста, к единственному дисплею и эквивалентно, единственному средству рендеринга. Как только этот контекст создается и установил текущие, нормальные вызовы OpenGL, будет допустимо для контекстов единственное средство рендеринга. Можно было использовать этот код при желании, чтобы циклично выполниться по доступным дисплеям и установить информацию о возможности для всех дисплеев, таким образом все средства рендеринга, не создавая drawable, ни будучи навязчивым пользователю.
Перечисление 3 , Настраивающее допустимый контекст рендеринга на дисплее
#include <OpenGL/OpenGL.h>
#include <ApplicationServices/ApplicationServices.h>
CGDirectDisplayID display = CGMainDisplayID ();
CGOpenGLDisplayMask cglDisplayMask =
CGDisplayIDToOpenGLDisplayMask (display);
{ // check capabilities of display represented by display mask
CGLPixelFormatAttribute attribs[] = {kCGLPFADisplayMask,
cglDisplayMask, NULL};
CGLPixelFormatObj pixelFormat = NULL;
long numPixelFormats = 0;
CGLContextObj cglContext = 0;
CGLContextObj curr_ctx = CGLGetCurrentContext ();
CGLChoosePixelFormat (attribs, &pixelFormat, &numPixelFormats);
if (pixelFormat) {
CGLCreateContext (pixelFormat, NULL, &cglContext);
CGLDestroyPixelFormat (pixelFormat);
if (cglContext) {
CGLSetCurrentContext (cglContext);
// test functionality here
CGLDestroyContext (cglContext);
}
}
CGLSetCurrentContext (curr_ctx); // reset current CGL context
} |
Теперь, когда у нас есть код, чтобы проверить версию ядра OpenGL, дополнительную строку и установить допустимое средство рендеринга на любом дисплее, мы можем расширить это для создания все включено пример проверки функциональности OpenGL, который разработчики могут использовать как есть или расширить для удовлетворения их индивидуальных потребностей. Следующие два раздела покрывают этот пример.
Обнаружение Функциональности с glCheck
glCheck является рядом подпрограмм, которые могут использоваться клиентами OpenGL для простого получения набора функций OpenGL для всех присоединенных дисплеев. Пример кода является factored дисплеем, как это - логическое подразделение возможностей оборудования. Даже при том, что два дисплея, возможно управляемые единственным устройством, никакой дисплей не будет управляться больше чем одним устройством. Код glCheck может быть установлен до использования OpenGL и затем обновлен для событий реконфигурирования дисплея. После того, как инициализированный, клиенты могут непосредственно получить доступ к структуре возможности, чтобы определить, имеет ли текущий контекст OpenGL определенную возможность. Сам пример кода содержит флаги для всего настоящего функций во время этой записи, но клиенты свободны удалить функции, которые они используют, если им нравится. Это может сохранить некоторую память, но так как код проверки функции вызывают чрезвычайно нечасто, это не требуется в целях производительности. Важно отметить, что код охватывает проверку и базовую версию OpenGL и дополнительную строку, таким образом, клиенты освобождены, чтобы просто проверить простой легкий флаг на определенную функцию. glCheck обеспечивает полную и легкую проверку на этапе выполнения, заменяющую тяжелые вызовы времени выполнения веса к glGetString и неполная проверка функции.
API очень прост и может быть вызван и от клиентов Какао и от Углерода. Используя API состоит из четырех шагов: инициализация структур и возможно подпрограмм уведомления, обновление структур, демонстрирующихся изменения конфигурации, проверка функцию или возможности по мере необходимости во время выполнения, и наконец освобождение структур и удаление любых подпрограмм уведомления на выходе.
Инициализация и для Какао и для Углерода выполняется с кодом, показанным в Перечислении 4. Этот код устанавливает глобальные переменные для хранения списка структур, числа активных дисплеев и универсального указателя процедуры для подпрограммы уведомления обновления, если используется. Приложения являются бесплатными хранить эту информацию, как им нравится, глобальные переменные используются для простоты в этой реализации в качестве примера. getCurrentCaps подпрограмма установки и обновления, сначала проверяющая, чтобы видеть, были ли возможности OpenGL ранее получены и если так, изменили их. HaveOpenGLCapsChanged подпрограмма довольно легка и ищет дополнительные дисплеи, или геометрия изменяются для указания изменения конфигурации дисплея. Если было изменение, мы освобождаем текущие структуры данных и продолжаем вниз нормальный путь инициализации. Сама инициализация проста, но не легка. Сначала мы передаем NULL как указатель структуры для установки флага этого, мы просто ищем число дисплеев, которые будут использоваться в выделении памяти структуры. Мы тогда выделяем память для дисплеев * размер GLCaps структура и пасует назад это в CheckOpenGLCaps подпрограмма для фактического получения прописных букв.
Перечисление 4 , инициализирующее структуры возможностей OpenGL
#include <stdlib.h>
#include <Carbon/Carbon.h>
#include <ApplicationServices/ApplicationServices.h>
#include "glCheck.h" // header code in Listing 8
// configuration info globals
GLCaps * gDisplayCaps = NULL; // array of GLCaps
CGDisplayCount gNumDisplays = 0; // number of displays
// related DM change notification
// (required for display config change notifications)
DMExtendedNotificationUPP gConfigEDMUPP = NULL;
static void getCurrentCaps (void)
{
if (gDisplayCaps &&
HaveOpenGLCapsChanged (gDisplayCaps, gNumDisplays)) { // if changed
free (gDisplayCaps); // set up to build new ones
gDisplayCaps = NULL;
}
if (!gDisplayCaps) { // if we do not have caps
// will just update number of displays
CheckOpenGLCaps (0, NULL, &gNumDisplays);
gDisplayCaps = (GLCaps*) malloc (sizeof (GLCaps) * gNumDisplays);
CheckOpenGLCaps (gNumDisplays, gDisplayCaps, &gNumDisplays);
}
} |
В то время как getCurrentCaps подпрограмма инициализации может позвониться в любое время, она включает существенное количество поисков строки, делающих его не особенно подходящий для выполнения на высоком показателе. Рекомендуется вызвать getCurrentCaps когда конфигурации дисплея изменяются, после того, как клиенты запускаются до выбора путей выполнения кода OpenGL и затем. Это не требуется, чтобы вызывать getCurrentCaps каждый кадр, или на каждом обновленном событии. Для приложений Какао этому рекомендуют один вызов getCurrentCaps от awakeFromNib первоначально и или установка метод обновления OpenGLView процедуры уведомления или использования менеджера дисплея Углерода при использовании процедуры уведомления не желаема. Используя update метод имеет вниз сторона проверки изменения дисплея чаще, чем необходимый, но HaveOpenGLCapsChanged проверка должна поддержать издержки на низком уровне. Приложения углерода могут вызвать getCurrentCaps первоначально в основном или другом расположении до выбора, который функции OpenGL использовать. Обновления обрабатываются в похожем методе для Какао, хотя для Углерода нужно просто использовать процедуру уведомления во всех случаях. Перечисление 5 и Перечисление 6 показывают код инициализации Какао и Углерода.
Код инициализации какао перечисления 5
#include <Cocoa/Cocoa.h>
#include <Carbon/Carbon.h> // for display manager functionality
#pragma mark ---- Display Manager Event Handling ----
// if notification procedures are used...
// update our GL configuration info based on display change notification
void handleConfigDMEvent (void *userData, short msg, void *notifyData)
{
if (kDMNotifyEvent == msg) { // post change notifications only
getCurrentCaps (); // from Listing 4
}
}
// ---------------------------------
// called for window resizes, moves and display changes
// (resize, depth and display config change)
// not required if an application is using display change notifications
- (void) update
{
[super update];
// do any application update stuff here...
if (![self inLiveResize]) { // if not doing live resize
// this call checks to see if the current config changed in a
// reasonably lightweight way to prevent expensive allocations
getCurrentCaps (); // from Listing 4
}
}
// ---------------------------------
- (void) awakeFromNib
{
// do app initialization stuff here...
// initialize OpenGL capabilities
// (this could be anytime prior to deciding on OpenGL code paths)
// get current GL capabilities for all displays
getCurrentCaps (); // from Listing 4
// configure display change notification (if desired)
gConfigEDMUPP = NewDMExtendedNotificationUPP (handleConfigDMEvent);
DMRegisterExtendedNotifyProc (gConfigEDMUPP, NULL, NULL, &psn);
} |
Код инициализации углерода перечисления 6
#include <Carbon/Carbon.h> // for display manager functionality
#pragma mark ---- Display Manager Event Handling ----
// update our GL configuration info based on display change notification
void handleConfigDMEvent (void *userData, short msg, void *notifyData)
{
if (kDMNotifyEvent == msg) { // post change notifications only
getCurrentCaps (); // from Listing 4
}
}
// ---------------------------------
main ()
{
// do client initialization stuff...
// initialize OpenGL capabilities
// get current GL capabilities for all displays
getCurrentCaps (); // from Listing 4
// configure display change notification
gConfigEDMUPP = NewDMExtendedNotificationUPP (handleConfigDMEvent);
DMRegisterExtendedNotifyProc (gConfigEDMUPP, NULL, NULL, &psn);
// client run loop...
// client exit stuff...
} |
Проверка определенные возможности легка и довольно проста выполнить. Обработанный разработан, чтобы использоваться по мере необходимости во время выполнения приложения во время генерации кадра. Перечисление 7 и Перечисление 8 показывают проверку возможностей Какао и Углерода, в частности в этом случае для GL_EXT_texture_rectangle (непитание двух поддержки текстурирования) функция. Предполагается, что приложения кэшировали значения текущего контекста и его формата пикселя. Пример предполагает, что они сохранены в self для примера Какао и глобально в случае Углерода, хотя приложения являются бесплатными сохранить их, как они требуют. Настоящее методологии является тем же в обоих случаях. Клиенты определят идентификацию средства рендеринга для текущего контекста на основе текущего виртуального формата экрана и идентификации средства рендеринга формата пикселя.
Как только приложение имеет текущую идентификацию средства рендеринга, которую они могут пересечь массив возможностей, найти структуру интереса путем соответствия средства рендеринга и затем непосредственно искать желаемую функцию. Этот индекс массива может тогда использоваться непосредственно для всего определения функции OpenGL, пока одно из двух событий не имеет место, ни один, который обновление контекста необходимо (см. Технические Вопросы и ответы QA1209, 'Обновляя Контексты OpenGL' для получения информации о том, когда обновления контекстов необходимы), или изменение конфигурации дисплея происходит, который может изменить массив конфигурации. Перечисление 7 исследования и Перечисление 8 для определенных подробных данных этой реализации в качестве примера.
Функции Listing 7 Testing OpenGL с glCheck и Какао
#include <Cocoa/Cocoa.h>
// assumes initialization code from Listing 4
{
// this finds the correct renderer via context virtual screen
// and pixel format renderer list then checks the capabilities list
// for texture rectangle capability (for example) it assumes gDisplayCaps
// and gNumDisplays are defined and initialized
BOOL hasCap = NO;
long renderer;
// match renderer using pixel format and context virtual screen
[[self pixelFormat] getValues:&renderer
forAttribute:NSOpenGLPFARendererID
forVirtualScreen:
[[self openGLContext] currentVirtualScreen]];
for (i = 0; i < gNumDisplays; i++) {
if ((renderer == gDisplayCaps[i].rendererID) && // if we match
gDisplayCaps[i].fTexRect) { // and have the capability
hasCap = YES;
break;
}
}
} |
Функции Listing 8 Testing OpenGL с glCheck и Углеродом
#include <agl/agl.h>
// assumes initialization code from Listing 4
{
// this finds the correct renderer via context virtual screen
// and pixel format renderer list then checks the capabilities list
// for texture rectangle capability (for example) it assumes gDisplayCaps
// and gNumDisplays are defined and initialized
Boolean hasCap = false;
GLint renderer = 0;
// match renderer using pixel format and context virtual screen
AGLPixelFormat pf = aglPixFmt; // first PF
GLint pfVS = 0, currVS = aglGetVirtualScreen (aglContext); // current VS
aglDescribePixelFormat (pf, AGL_VIRTUAL_SCREEN, &pfVS); // get VS for PF
while ((pfVS != currVS) && pf) { // while PF's and the VS's do not match
pf = aglNextPixelFormat (pf); // get next PF
aglDescribePixelFormat (pf, AGL_VIRTUAL_SCREEN, &pfVS); // get VS
}
if (pf) // if we matched VS (we should)
aglDescribePixelFormat(pf, AGL_RENDERER_ID, &renderer); // get rend
for (i = 0; i < gNumDisplays; i++) {
if ((renderer == gDisplayCaps[i].rendererID) && // if we match
DisplayCaps[i]. fTexRect) { // and have the capability
hasCap = YES;
break;
}
}
} |
Наконец, Перечисление 9 показывает общий код, который должен быть выполнен на выходе к выделенной свободной памяти и расположить любые обратные вызовы, которые мы установили. Перечисление принимает те же глобальные переменные, используемые в предыдущих примерах кода.
Перечисление 9 , располагающее записи возможности OpenGL и уведомления
#include <stdlib.h>
#include <Carbon/Carbon.h>
// assumes initialization code from Listing 4
// if notification installed, remove display change notification
if (gConfigEDMUPP) { // dispose UPP for DM notifications
DisposeDMExtendedNotificationUPP (gConfigEDMUPP);
gConfigEDMUPP = NULL;
}
// free memory for display capabilities records
if (gDisplayCaps) {
free (gDisplayCaps);
gDisplayCaps = NULL;
} |
Исходный код glCheck
glcheck пример кода в Перечислении 10 и Перечислении 11 показывает реализацию в качестве примера проверки возможностей, обсужденной в этом техническом примечании. Этот пример кода имеет заголовочный файл, определяющий простую структуру с помощью базируемых флагов функции, показывающих, какие возможности, которыми обладает определенное средство рендеринга, детализированы в Перечислении 10.
Перечисление 10 код проверки возможностей OpenGL: glCheck.h
// glcheck allows developer to check the hardware capabilities of all GPU's
// returning an array of records reflecting the attached hardware. This
// list can be regenerated on Display Manager notifications to keep the
// client update to on capabilities and setup changes. This is provided as
// sample to allow developers the freedom to check as few or as many
// conditions and capabilities as they would like or add their own checks
#include <Carbon/Carbon.h>
#include <ApplicationServices/ApplicationServices.h>
typedef struct {
// developers can add capabilities as required
CGDirectDisplayID cgDisplayID; // CG display ID (main identifier)
unsigned long displayID; // QD display ID
GDHandle hGDevice; // graphics device handle
CGOpenGLDisplayMask cglDisplayMask; // CGL display mask
// current (at time of look up) device geometry
long deviceWidth; // pixel width
long deviceHeight; // pixel width
long deviceOriginX; // left location of device (relative to main device)
long deviceOriginY; // upper location of device (relative to main device)
short deviceDepth; // pixel depth in bits
short deviceRefresh; // integer refresh rate in Hz
// Renderer info
long deviceVRAM; // video memory in bytes
long deviceTextureRAM; // uses current mode (geometry, pixel depth, etc.)
unsigned long rendererID; // renderer ID
char strRendererName [256]; // name of hardware renderer
char strRendererVendor [256]; // name of hardware renderer vendor
char strRendererVersion [256]; // string rep of hardware renderer version
bool fullScreenCapable; // does device support full screen
// can add more device specs as you want
// Renderer Caps
long textureUnits; // standard gl path max number of texture units
long maxTextureSize; // maximum 1D and 2D texture size supported
long max3DTextureSize; // maximum 3D texture size supported
long maxCubeMapTextureSize; // maximum cube map texture size supported
long maxRectTextureSize; // maximum rectangular texture size supported
// OpenGL version support
unsigned short glVersion; // bcd gl version (ie. 1.4 is 0x0140)
// Functionality
bool fSpecularVector; // GL_APPLE_specular_vector
bool fTransformHint; // GL_APPLE_transform_hint
bool fPackedPixels; // GL_APPLE_packed_pixels or 1.2+
bool fClientStorage; // GL_APPLE_client_storage
bool fYCbCr; // GL_APPLE_ycbcr_422 (YUV texturing)
bool fTextureRange; // GL_APPLE_texture_range (AGP texturing)
bool fFence; // GL_APPLE_fence
bool fVAR; // GL_APPLE_vertex_array_range
bool fVAO; // GL_APPLE_vertex_array_object
bool fElementArray; // GL_APPLE_element_array
bool fVPEvals; // GL_APPLE_vertex_program_evaluators
bool fFloatPixels; // GL_APPLE_float_pixels
bool fFlushRenderer; // GL_APPLE_flush_render
bool fPixelBuffer; // GL_APPLE_pixel_buffer
bool fImaging; // GL_ARB_imaging (not required in 1.2+)
bool fTransposeMatrix; // GL_ARB_transpose_matrix or 1.3+
bool fMultitexture; // GL_ARB_multitexture or 1.3+
bool fTexEnvAdd; // GL_ARB_texture_env_add, GL_EXT_texture_env_add or 1.3+
bool fTexEnvCombine; // GL_ARB_texture_env_combine or 1.3+
bool fTexEnvDot3; // GL_ARB_texture_env_dot3 or 1.3+
bool fTexEnvCrossbar; // GL_ARB_texture_env_crossbar or 1.4+
bool fTexCubeMap; // GL_ARB_texture_cube_map or 1.3+
bool fTexCompress; // GL_ARB_texture_compression or 1.3+
bool fMultisample; // GL_ARB_multisample or 1.3+ (Anti-aliasing)
bool fTexBorderClamp; // GL_ARB_texture_border_clamp or 1.3+
bool fPointParam; // GL_ARB_point_parameters or 1.4+
bool fVertexProg; // GL_ARB_vertex_program
bool fFragmentProg; // GL_ARB_fragment_program
bool fTexMirrorRepeat; // GL_ARB_texture_mirrored_repeat or 1.4+
bool fDepthTex; // GL_ARB_depth_texture or 1.4+
bool fShadow; // GL_ARB_shadow or 1.4+
bool fShadowAmbient; // GL_ARB_shadow_ambient
bool fVertexBlend; // GL_ARB_vertex_blend
bool fWindowPos; // GL_ARB_window_pos or 1.4+
bool fTex3D; // GL_EXT_texture3D or 1.2+
bool fClipVolHint; // GL_EXT_clip_volume_hint
bool fRescaleNorm; // GL_EXT_rescale_normal or 1.2+
bool fBlendColor; // GL_EXT_blend_color or GL_ARB_imaging
bool fBlendMinMax; // GL_EXT_blend_minmax or GL_ARB_imaging
bool fBlendSub; // GL_EXT_blend_subtract or GL_ARB_imaging
bool fCVA; // GL_EXT_compiled_vertex_array
bool fTexLODBias; // GL_EXT_texture_lod_bias or 1.4+
bool fABGR; // GL_EXT_abgr
bool fBGRA; // GL_EXT_bgra or 1.2+
bool fTexFilterAniso; // GL_EXT_texture_filter_anisotropic
bool fPaletteTex; // GL_EXT_paletted_texture
bool fShareTexPalette; // GL_EXT_shared_texture_palette
bool fSecColor; // GL_EXT_secondary_color or 1.4+
bool fTexCompressS3TC; // GL_EXT_texture_compression_s3tc
bool fTexRect; // GL_EXT_texture_rectangle
bool fFogCoord; // GL_EXT_fog_coord
bool fDrawRangeElements; // GL_EXT_draw_range_elements
bool fStencilWrap; // GL_EXT_stencil_wrap or 1.4+
bool fBlendFuncSep; // GL_EXT_blend_func_separate or 1.4+
bool fMultiDrawArrays; // GL_EXT_multi_draw_arrays or 1.4+
bool fShadowFunc; // GL_EXT_shadow_funcs
bool fStencil2Side; // GL_EXT_stencil_two_side
bool fColorSubtable; // GL_EXT_color_subtable or GL_ARB_imaging
bool fConvolution; // GL_EXT_convolution or GL_ARB_imaging
bool fHistogram; // GL_EXT_histogram or GL_ARB_imaging
bool fColorTable; // GL_SGI_color_table or GL_ARB_imaging
bool fColorMatrix; // GL_SGI_color_matrix
bool fTexEdgeClamp; // GL_SGIS_texture_edge_clamp or 1.2+
bool fGenMipmap; // GL_SGIS_generate_mipmap or 1.4+
bool fTexLOD; // GL_SGIS_texture_lod or 1.2+
bool fPointCull; // GL_ATI_point_cull_mode
bool fTexMirrorOnce; // GL_ATI_texture_mirror_once
bool fPNtriangles; // GL_ATI_pn_triangles or GL_ATIX_pn_triangles
bool fTextFragShader; // GL_ATI_text_fragment_shader
bool fBlendEqSep; // GL_ATI_blend_equation_separate
bool fBlendWeightMinMax; // GL_ATI_blend_weighted_minmax
bool fCombine3; // GL_ATI_texture_env_combine3
bool fSepStencil; // GL_ATI_separate_stencil
bool fArrayRevComps4Byte; // GL_ATI_array_rev_comps_in_4_bytes
bool fPointSprite; // GL_NV_point_sprite
bool fRegCombiners; // GL_NV_register_combiners
bool fRegCombiners2; // GL_NV_register_combiners2
bool fTexEnvCombine4; // GL_NV_texture_env_combine4
bool fBlendSquare; // GL_NV_blend_square or 1.4+
bool fFogDist; // GL_NV_fog_distance
bool fMultisampleFilterHint; // GL_NV_multisample_filter_hint
bool fTexGenReflect; // GL_NV_texgen_reflection
bool fTexShader; // GL_NV_texture_shader
bool fTexShader2; // GL_NV_texture_shader2
bool fTexShader3; // GL_NV_texture_shader3
bool fDepthClamp; // GL_NV_depth_clamp
bool fLightMaxExp; // GL_NV_light_max_exponent
bool fConvBorderModes; // GL_HP_convolution_border_modes or GL_ARB_imaging
bool fRasterPosClip; // GL_IBM_rasterpos_clip
} GLCaps;
// this does a reasonable check to see if things have changed without being
// too heavy weight; returns 1 if changed 0 if not
// checks num displays, displayID, displayMask, each display geometry and
// renderer VRAM and ID
unsigned char HaveOpenGLCapsChanged (GLCaps aDisplayCaps[],
CGDisplayCount dspyCnt);
// This will walk all active displays and gather information about their
// hardware renderer
// An array length (maxDisplays) and array of GLCaps are passed in. Up to
// maxDisplays of the array are filled in with the displays meeting the
// specified criteria. The actual number of displays filled in is returned
// in dspyCnt. Calling this function with maxDisplays of 0 will just
// return the number of displays in dspyCnt.
// Developers should note this is NOT an exhaustive list of all the
// capabilities one could query, nor a required set of capabilities,
// feel free to add or subtract queries as you find helpful for your
// application/use.
// one note on mirrored displays... if the display configuration is
// changed it is possible (and likely) that the current active display
// in a mirrored configuration (as identified by the OpenGL Display Mask)
// will change if the mirrored display is removed.
// This is due to the preference of selection the external display as
// the active display. This may affect full screen apps which should
// always detect display configuration changes and respond accordingly.
void CheckOpenGLCaps (CGDisplayCount maxDisplays,
GLCaps * aDisplayCaps,
CGDisplayCount * dspyCnt); |
Исходный код, как показано в Перечислении 11, имеет много разделов. В первом разделе дисплеи перечислены и выполнены с помощью итераций при приведении к таблица со структурой возможностей для каждого дисплея. Следующая информация раздела собирается о каждом дисплее и средстве рендеринга поочередно. Сначала основной CoreGraphics и Углерод выводят на экран информацию для упрощения использования или приложениями Какао или Углерода. Затем, информация об устройстве Углерода используется для получения полного экрана средства рендеринга и пределов памяти. Наконец мы используем наш код CGL, чтобы создать контекст рендеринга и получить определенную информацию OpenGL для всей поддерживаемой функциональности и некоторых пределов в качестве примера. Разработчики свободны сократить или развернуть эту проверку как требуется их определенное приложение. Наконец, как покрыто ранее, CheckOpenGLCaps не разработан для производительности критические разделы кода, рекомендуется, чтобы эту подпрограмму вызвали один раз после того, как приложение запускается и затем на любых изменениях конфигурации дисплея и для клиентов для прямого доступа к значениям параметра, как обрисовано в общих чертах ранее.
Перечисление 11 код проверки возможностей OpenGL: glCheck.c
#include "glCheck.h"
#include <OpenGL/OpenGL.h>
#include <AGL/agl.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <OpenGL/glext.h>
#include <string.h>
// -------------------------
// local CF dictionary routines
static long _getDictLong (CFDictionaryRef refDict, CFStringRef key)
{
long int_value;
CFNumberRef num_value = (CFNumberRef)CFDictionaryGetValue(refDict, key);
if (!num_value) // if can't get a number for the dictionary
return -1; // fail
// or if cant convert it
if (!CFNumberGetValue(num_value, kCFNumberLongType, &int_value))
return -1; // fail
return int_value; // otherwise return the long value
}
static double _getDictDouble (CFDictionaryRef refDict, CFStringRef key)
{
double double_value;
CFNumberRef num_value = (CFNumberRef)CFDictionaryGetValue(refDict, key);
if (!num_value) // if can't get a number for the dictionary
return -1; // fail
// or if cant convert it
if (!CFNumberGetValue(num_value, kCFNumberDoubleType, &double_value))
return -1; // fail
return double_value; // otherwise return the long value
}
// -------------------------
// this does a reasonable check to see if things have changed without being
// too heavy weight; returns 1 if changed 0 if not
// checks num displays, displayID, displayMask, each display geometry and
// renderer VRAM and ID
unsigned char HaveOpenGLCapsChanged (GLCaps aDisplayCaps[],
CGDisplayCount dspyCnt)
{
CGDisplayCount maxDisplays = 32;
CGDirectDisplayID activeDspys[32];
CGDisplayErr error;
short i;
CGDisplayCount newDspyCnt = 0;
if (NULL == aDisplayCaps) return 1;
error = CGGetActiveDisplayList(maxDisplays, activeDspys, &newDspyCnt);
// if error getting list mark as changed
if (error) return 1;
// if number of displays not equal
if (dspyCnt != newDspyCnt) return 1;
for (i = 0; i < dspyCnt; i++) {
// get device ids
if (aDisplayCaps[i].cgDisplayID != activeDspys[i]) return 1;
if (aDisplayCaps[i].cglDisplayMask !=
CGDisplayIDToOpenGLDisplayMask(activeDspys[i])) return 1;
// get current geometry
{
CGRect displayRect = CGDisplayBounds (activeDspys[i]);
// get mode dictionary
CFDictionaryRef dispMode = CGDisplayCurrentMode (activeDspys[i]);
// check for all geometry matches
if (aDisplayCaps[i].deviceWidth != (long) displayRect.size.width)
return 1;
if (aDisplayCaps[i].deviceHeight != (long) displayRect.size.height)
return 1;
if (aDisplayCaps[i].deviceOriginX != (long) displayRect.origin.x)
return 1;
if (aDisplayCaps[i].deviceOriginY != (long) displayRect.origin.y)
return 1;
if (aDisplayCaps[i].deviceDepth !=
(short) _getDictLong (dispMode, kCGDisplayBitsPerPixel))
return 1;
if (aDisplayCaps[i].deviceRefresh !=
(short)(_getDictDouble (dispMode, kCGDisplayRefreshRate) + 0.5))
return 1; // round to GLint
}
// get renderer info based on gDevice
{
CGLRendererInfoObj info;
long j, numRenderers = 0, rv = 0;
CGLError err = 0;
long deviceVRAM; // video memory in bytes
unsigned long rendererID; // renderer ID
err = CGLQueryRendererInfo (aDisplayCaps[i].cglDisplayMask,
&info, &numRenderers);
if(0 == err) {
CGLDescribeRenderer (info, 0, kCGLRPRendererCount, &numRenderers);
for (j = 0; j < numRenderers; j++) {
// find accelerated renderer (assume only one)
CGLDescribeRenderer (info, j, kCGLRPAccelerated, &rv);
if (true == rv) { // if accelerated
// what is the renderer ID
CGLDescribeRenderer (info, j, kCGLRPRendererID, &rendererID);
if (rendererID != aDisplayCaps[i].rendererID) // check match
return 1;
// what is the VRAM
CGLDescribeRenderer (info, j, kCGLRPVideoMemory, &deviceVRAM);
if (deviceVRAM != aDisplayCaps[i].deviceVRAM) // check match
return 1;
break; // done
}
}
}
CGLDestroyRendererInfo (info);
}
}
return 0;
}
// -------------------------
// This will walk all active displays and gather information about their
// hardware renderer
// An array length (maxDisplays) and array of GLCaps are passed in. Up to
// maxDisplays of the array are filled in with the displays meeting the
// specified criteria. The actual number of displays filled in is returned
// in dspyCnt. Calling this function with maxDisplays of 0 will just
// return the number of displays in dspyCnt.
// Developers should note this is NOT an exhaustive list of all the
// capabilities one could query, nor a required set of capabilities,
// feel free to add or subtract queries as you find helpful for your
// application/use.
// one note on mirrored displays... if the display configuration is
// changed it is possible (and likely) that the current active display
// in a mirrored configuration (as identified by the OpenGL Display Mask)
// will change if the mirrored display is removed.
// This is due to the preference of selection the external display as
// the active display. This may affect full screen apps which should
// always detect display configuration changes and respond accordingly.
void CheckOpenGLCaps (CGDisplayCount maxDspys,
GLCaps dCaps[],
CGDisplayCount * dCnt)
{
CGLContextObj curr_ctx = 0;
CGDirectDisplayID dspys[32];
CGDisplayErr err;
short i;
short size = sizeof (GLCaps);
// no devices
*dCnt = 0;
if (maxDspys == 0) { // find number of displays
*dCnt = 0;
err = CGGetActiveDisplayList (32, dspys, dCnt);
if (err) // err getting list
*dCnt = 0; // 0 displays since can't correctly find any
// zero list to ensure the routines are used correctly
memset (dspys, 0, sizeof (CGDirectDisplayID) * *dCnt);
return; // return dCnt
}
if (NULL == dCaps) return;
err = CGGetActiveDisplayList(maxDspys, dspys, dCnt);
if (err) return; // err getting list
if (0 == *dCnt) return; // no displays
memset (dCaps, 0, size * *dCnt); // zero memory
for (i = 0; i < *dCnt; i++) {
// get device ids
dCaps[i].cgDisplayID = dspys[i];
dCaps[i].cglDisplayMask = CGDisplayIDToOpenGLDisplayMask(dspys[i]);
{ // get current geometry
CGRect displayRect = CGDisplayBounds (dspys[i]);
// get mode dictionary
CFDictionaryRef dispMode = CGDisplayCurrentMode (dspys[i]);
dCaps[i].deviceWidth = (long) displayRect.size.width;
dCaps[i].deviceHeight = (long) displayRect.size.height;
dCaps[i].deviceOriginX = (long) displayRect.origin.x;
dCaps[i].deviceOriginY = (long) displayRect.origin.y;
dCaps[i].deviceDepth = (short) _getDictLong (dispMode,
kCGDisplayBitsPerPixel);
dCaps[i].deviceRefresh = (short) (_getDictDouble (dispMode,
kCGDisplayRefreshRate) + 0.5);
}
{ // find gDevice device by bounds
GDHandle hGD;
for (hGD = GetDeviceList (); hGD; hGD = GetNextDevice (hGD))
{
if (!TestDeviceAttribute (hGD, screenDevice) ||
!TestDeviceAttribute (hGD, screenActive))
continue;
// if postion and sizes match
if (((*hGD)->gdRect.top == dCaps[i].deviceOriginY) &&
((*hGD)->gdRect.left == dCaps[i].deviceOriginX) &&
(((*hGD)->gdRect.bottom - (*hGD)->gdRect.top) ==
dCaps[i].deviceHeight) &&
(((*hGD)->gdRect.right - (*hGD)->gdRect.left) ==
dCaps[i].deviceWidth)) {
dCaps[i].hGDevice = hGD;
break;
}
}
if (dCaps[i].hGDevice == NULL)
return; // err
if (noErr != DMGetDisplayIDByGDevice (dCaps[i].hGDevice,
&dCaps[i].displayID, false))
dCaps[i].displayID = 0; // err getting display ID
}
{ // get renderer info based on gDevice
CGLRendererInfoObj info;
long j, numRenderers = 0, rv = 0;
CGLError err = 0;
err = CGLQueryRendererInfo (dCaps[i].cglDisplayMask,
&info,
&numRenderers);
if(0 == err) {
CGLDescribeRenderer (info, 0, kCGLRPRendererCount, &numRenderers);
for (j = 0; j < numRenderers; j++) {
// find accelerated renderer (assume only one)
CGLDescribeRenderer (info, j, kCGLRPAccelerated, &rv);
if (true == rv) { // if accelerated
// what is the renderer ID
CGLDescribeRenderer (info, j, kCGLRPRendererID,
&dCaps[i].rendererID);
// can we do full screen?
CGLDescribeRenderer (info, j, kCGLRPFullScreen, &rv);
dCaps[i].fullScreenCapable = (bool) rv;
// what is the VRAM?
CGLDescribeRenderer (info, j, kCGLRPVideoMemory,
&dCaps[i].deviceVRAM);
// what is the current texture memory?
CGLDescribeRenderer (info, j, kCGLRPTextureMemory,
&dCaps[i].deviceTextureRAM);
break; // done
}
}
}
CGLDestroyRendererInfo (info);
}
{ // build context and context specific info
CGLPixelFormatAttribute attribs[] = { kCGLPFADisplayMask,
dCaps[i].cglDisplayMask,
NULL };
CGLPixelFormatObj pixelFormat = NULL;
long numPixelFormats = 0;
CGLContextObj cglContext;
curr_ctx = CGLGetCurrentContext (); // get current CGL context
CGLChoosePixelFormat (attribs, &pixelFormat, &numPixelFormats);
if (pixelFormat) {
CGLCreateContext(pixelFormat, NULL, &cglContext);
CGLDestroyPixelFormat (pixelFormat);
CGLSetCurrentContext (cglContext);
if (cglContext) {
const GLubyte * strExt;
const GLubyte * strRend;
const GLubyte * strVers;
const GLubyte * strVend;
// get renderer strings
strRend = glGetString (GL_RENDERER);
strncpy (dCaps[i].strRendererName, strRend, 255);
strVend = glGetString (GL_VENDOR);
strncpy (dCaps[i].strRendererVendor, strVend, 255);
strVers = glGetString (GL_VERSION);
strncpy (dCaps[i].strRendererVersion, strVers, 255);
{ // get BCD version
short j = 0;
short shiftVal = 8;
while (((strVers[j] <= '9') && (strVers[j] >= '0')) ||
(strVers[j] == '.')) {
// get only basic version info (until first non-digit or non-.)
if ((strVers[j] <= '9') && (strVers[j] >= '0')) {
dCaps[i].glVersion += (strVers[j] - '0') << shiftVal;
shiftVal -= 4;
}
j++;
}
}
strExt = glGetString (GL_EXTENSIONS);
// get caps
glGetIntegerv (GL_MAX_TEXTURE_UNITS,
&dCaps[i].textureUnits);
glGetIntegerv (GL_MAX_TEXTURE_SIZE,
&dCaps[i].maxTextureSize);
glGetIntegerv (GL_MAX_3D_TEXTURE_SIZE,
&dCaps[i].max3DTextureSize);
glGetIntegerv (GL_MAX_CUBE_MAP_TEXTURE_SIZE,
&dCaps[i].maxCubeMapTextureSize);
// get functionality info
dCaps[i].fSpecularVector =
gluCheckExtension ("GL_APPLE_specular_vector", strExt);
dCaps[i].fTransformHint =
gluCheckExtension ("GL_APPLE_transform_hint", strExt);
dCaps[i].fPackedPixels =
gluCheckExtension ("GL_APPLE_packed_pixels", strExt) ||
gluCheckExtension ("GL_APPLE_packed_pixel", strExt) ||
(dCaps[i].glVersion >= 0x0120);
dCaps[i].fClientStorage =
gluCheckExtension ("GL_APPLE_client_storage", strExt);
dCaps[i].fYCbCr =
gluCheckExtension ("GL_APPLE_ycbcr_422", strExt);
dCaps[i].fTextureRange =
gluCheckExtension ("GL_APPLE_texture_range", strExt);
dCaps[i].fFence =
gluCheckExtension ("GL_APPLE_fence", strExt);
dCaps[i].fVAR =
gluCheckExtension ("GL_APPLE_vertex_array_range", strExt);
dCaps[i].fVAO =
gluCheckExtension ("GL_APPLE_vertex_array_object", strExt);
dCaps[i].fElementArray =
gluCheckExtension ("GL_APPLE_element_array", strExt);
dCaps[i].fVPEvals =
gluCheckExtension("GL_APPLE_vertex_program_evaluators",strExt);
dCaps[i].fFloatPixels =
gluCheckExtension ("GL_APPLE_float_pixels", strExt);
dCaps[i].fFlushRenderer =
gluCheckExtension ("GL_APPLE_flush_render", strExt);
dCaps[i].fPixelBuffer =
gluCheckExtension ("GL_APPLE_pixel_buffer", strExt);
dCaps[i].fImaging =
gluCheckExtension ("GL_ARB_imaging", strExt);
dCaps[i].fTransposeMatrix =
gluCheckExtension ("GL_ARB_transpose_matrix", strExt) ||
(dCaps[i].glVersion >= 0x0130);
dCaps[i].fMultitexture =
gluCheckExtension ("GL_ARB_multitexture", strExt) ||
(dCaps[i].glVersion >= 0x0130);
dCaps[i].fTexEnvAdd =
gluCheckExtension ("GL_ARB_texture_env_add", strExt) ||
gluCheckExtension ("GL_EXT_texture_env_add", strExt) ||
(dCaps[i].glVersion >= 0x0130);
dCaps[i].fTexEnvCombine =
gluCheckExtension ("GL_ARB_texture_env_combine", strExt) ||
(dCaps[i].glVersion >= 0x0130);
dCaps[i].fTexEnvDot3 =
gluCheckExtension ("GL_ARB_texture_env_dot3", strExt) ||
(dCaps[i].glVersion >= 0x0130);
dCaps[i].fTexEnvCrossbar =
gluCheckExtension ("GL_ARB_texture_env_crossbar", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fTexCubeMap =
gluCheckExtension ("GL_ARB_texture_cube_map", strExt) ||
(dCaps[i].glVersion >= 0x0130);
dCaps[i].fTexCompress =
gluCheckExtension ("GL_ARB_texture_compression", strExt) ||
(dCaps[i].glVersion >= 0x0130);
dCaps[i].fMultisample =
gluCheckExtension ("GL_ARB_multisample", strExt) ||
(dCaps[i].glVersion >= 0x0130);
dCaps[i].fTexBorderClamp =
gluCheckExtension ("GL_ARB_texture_border_clamp", strExt) ||
(dCaps[i].glVersion >= 0x0130);
dCaps[i].fPointParam =
gluCheckExtension ("GL_ARB_point_parameters", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fVertexProg =
gluCheckExtension ("GL_ARB_vertex_program", strExt);
dCaps[i].fFragmentProg =
gluCheckExtension ("GL_ARB_fragment_program", strExt);
dCaps[i].fTexMirrorRepeat =
gluCheckExtension ("GL_ARB_texture_mirrored_repeat", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fDepthTex =
gluCheckExtension ("GL_ARB_depth_texture", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fShadow =
gluCheckExtension ("GL_ARB_shadow", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fShadowAmbient =
gluCheckExtension ("GL_ARB_shadow_ambient", strExt);
dCaps[i].fVertexBlend =
gluCheckExtension ("GL_ARB_vertex_blend", strExt);
dCaps[i].fWindowPos =
gluCheckExtension ("GL_ARB_window_pos", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fTex3D =
gluCheckExtension ("GL_EXT_texture3D", strExt) ||
(dCaps[i].glVersion >= 0x0120);
dCaps[i].fClipVolHint =
gluCheckExtension ("GL_EXT_clip_volume_hint", strExt);
dCaps[i].fRescaleNorm =
gluCheckExtension ("GL_EXT_rescale_normal", strExt) ||
(dCaps[i].glVersion >= 0x0120);
dCaps[i].fBlendColor =
gluCheckExtension ("GL_EXT_blend_color", strExt) ||
gluCheckExtension ("GL_ARB_imaging", strExt);
dCaps[i].fBlendMinMax =
gluCheckExtension ("GL_EXT_blend_minmax", strExt) ||
gluCheckExtension ("GL_ARB_imaging", strExt);
dCaps[i].fBlendSub =
gluCheckExtension ("GL_EXT_blend_subtract", strExt) ||
gluCheckExtension ("GL_ARB_imaging", strExt);
dCaps[i].fCVA =
gluCheckExtension ("GL_EXT_compiled_vertex_array", strExt);
dCaps[i].fTexLODBias =
gluCheckExtension ("GL_EXT_texture_lod_bias", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fABGR =
gluCheckExtension ("GL_EXT_abgr", strExt);
dCaps[i].fBGRA =
gluCheckExtension ("GL_EXT_bgra", strExt) ||
(dCaps[i].glVersion >= 0x0120);
dCaps[i].fTexFilterAniso =
gluCheckExtension ("GL_EXT_texture_filter_anisotropic",strExt);
dCaps[i].fPaletteTex =
gluCheckExtension ("GL_EXT_paletted_texture", strExt);
dCaps[i].fShareTexPalette =
gluCheckExtension ("GL_EXT_shared_texture_palette", strExt);
dCaps[i].fSecColor =
gluCheckExtension ("GL_EXT_secondary_color", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fTexCompressS3TC =
gluCheckExtension ("GL_EXT_texture_compression_s3tc", strExt);
dCaps[i].fTexRect =
gluCheckExtension ("GL_EXT_texture_rectangle", strExt);
dCaps[i].fFogCoord =
gluCheckExtension ("GL_EXT_fog_coord", strExt);
dCaps[i].fDrawRangeElements =
gluCheckExtension ("GL_EXT_draw_range_elements", strExt);
dCaps[i].fStencilWrap =
gluCheckExtension ("GL_EXT_stencil_wrap", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fBlendFuncSep =
gluCheckExtension ("GL_EXT_blend_func_separate", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fMultiDrawArrays =
gluCheckExtension ("GL_EXT_multi_draw_arrays", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fShadowFunc =
gluCheckExtension ("GL_EXT_shadow_funcs", strExt);
dCaps[i].fStencil2Side =
gluCheckExtension ("GL_EXT_stencil_two_side", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fColorSubtable =
gluCheckExtension ("GL_EXT_color_subtable", strExt) ||
gluCheckExtension ("GL_ARB_imaging", strExt);
dCaps[i].fConvolution =
gluCheckExtension ("GL_EXT_convolution", strExt) ||
gluCheckExtension ("GL_ARB_imaging", strExt);
dCaps[i].fHistogram =
gluCheckExtension ("GL_EXT_histogram", strExt) ||
gluCheckExtension ("GL_ARB_imaging", strExt);
dCaps[i].fColorTable =
gluCheckExtension ("GL_SGI_color_table", strExt) ||
gluCheckExtension ("GL_ARB_imaging", strExt);
dCaps[i].fColorMatrix =
gluCheckExtension ("GL_SGI_color_matrix", strExt) ||
gluCheckExtension ("GL_ARB_imaging", strExt);
dCaps[i].fTexEdgeClamp =
gluCheckExtension ("GL_SGIS_texture_edge_clamp", strExt) ||
(dCaps[i].glVersion >= 0x0120);
dCaps[i].fGenMipmap =
gluCheckExtension ("GL_SGIS_generate_mipmap", strExt);
dCaps[i].fTexLOD =
gluCheckExtension ("GL_SGIS_texture_lod", strExt) ||
(dCaps[i].glVersion >= 0x0120);
dCaps[i].fPointCull =
gluCheckExtension ("GL_ATI_point_cull_mode", strExt);
dCaps[i].fTexMirrorOnce =
gluCheckExtension ("GL_ATI_texture_mirror_once", strExt);
dCaps[i].fPNtriangles =
gluCheckExtension ("GL_ATI_pn_triangles", strExt) ||
gluCheckExtension ("GL_ATIX_pn_triangles", strExt);
dCaps[i].fTextFragShader =
gluCheckExtension ("GL_ATI_text_fragment_shader", strExt);
dCaps[i].fBlendEqSep =
gluCheckExtension ("GL_ATI_blend_equation_separate", strExt);
dCaps[i].fBlendWeightMinMax =
gluCheckExtension ("GL_ATI_blend_weighted_minmax", strExt);
dCaps[i].fCombine3 =
gluCheckExtension ("GL_ATI_texture_env_combine3", strExt);
dCaps[i].fSepStencil =
gluCheckExtension ("GL_ATI_separate_stencil", strExt);
dCaps[i].fArrayRevComps4Byte =
gluCheckExtension ("GL_ATI_array_rev_comps_in_4_bytes",strExt);
dCaps[i].fPointSprite =
gluCheckExtension ("GL_NV_point_sprite", strExt);
dCaps[i].fRegCombiners =
gluCheckExtension ("GL_NV_register_combiners", strExt);
dCaps[i].fRegCombiners2 =
gluCheckExtension ("GL_NV_register_combiners2", strExt);
dCaps[i].fTexEnvCombine4 =
gluCheckExtension ("GL_NV_texture_env_combine4", strExt);
dCaps[i].fBlendSquare =
gluCheckExtension ("GL_NV_blend_square", strExt) ||
(dCaps[i].glVersion >= 0x0140);
dCaps[i].fFogDist =
gluCheckExtension ("GL_NV_fog_distance", strExt);
dCaps[i].fMultisampleFilterHint =
gluCheckExtension ("GL_NV_multisample_filter_hint", strExt);
dCaps[i].fTexGenReflect =
gluCheckExtension ("GL_NV_texgen_reflection", strExt);
dCaps[i].fTexShader =
gluCheckExtension ("GL_NV_texture_shader", strExt);
dCaps[i].fTexShader2 =
gluCheckExtension ("GL_NV_texture_shader2", strExt);
dCaps[i].fTexShader3 =
gluCheckExtension ("GL_NV_texture_shader3", strExt);
dCaps[i].fDepthClamp =
gluCheckExtension ("GL_NV_depth_clamp", strExt);
dCaps[i].fLightMaxExp =
gluCheckExtension ("GL_NV_light_max_exponent", strExt);
dCaps[i].fRasterPosClip =
gluCheckExtension ("GL_IBM_rasterpos_clip", strExt);
dCaps[i].fConvBorderModes =
gluCheckExtension ("GL_HP_convolution_border_modes", strExt) ||
gluCheckExtension ("GL_ARB_imaging", strExt);
if (dCaps[i].fTexRect) // only check if extension supported
glGetIntegerv (GL_MAX_RECTANGLE_TEXTURE_SIZE_EXT,
&dCaps[i].maxRectTextureSize);
else
dCaps[i].maxRectTextureSize = 0;
CGLDestroyContext (cglContext);
}
}
CGLSetCurrentContext (curr_ctx); // reset current CGL context
}
}
} |
Это завершает обсуждение функциональности OpenGL. Понимание отношения ядра к расширенным командам является ключевым для простой навигации и использования OpenGL на всех поддерживаемых платформах. Это Техническое примечание обсудило базовую и расширенную функциональность и как определить, поддерживается ли определенная функция. Кроме того, создание допустимых контекстов рендеринга было обсуждено в контексте интерфейса Mac OS X OpenGL API's. Наконец, конкретный пример того, как полностью проверить на доступные системные средства рендеринга и их функциональность, предоставлен.
История версии документа
| Дата | Примечания |
|---|---|
| 29.12.2003 | Новый документ, обсуждающий OpenGL проект API, и как получить доступ к полномочиям аппаратных и программных средств рендеринга. |