Руководство программиста в Photon (1037671), страница 51
Текст из файла (страница 51)
PhDrawContext_t *olddc;
PdOffscreenContext_t *context1, *context2;
PhArea_t rsrc,rdst;
/* Создаём область 100x100 в собственном формате экрана */
context1=PdCreateOffscreenContext(0,100,100,0);
if (context1 == NULL)
{
/* Ошибка */
}
/* Делаем её текущим контекстом и рисуем в ней пурпурный прямоугольник */
olddc=PhDCSetCurrent(context1);
PgSetFillColor(Pg_PURPLE);
PgDrawIRect(0,0,99,99,Pg_DRAW_FILL);
PgFlush(); /* Рисование прямоугольника */
PhDCSetCurrent(olddc);
/* Копируем контекст 1 и рисуем белый прямоугольник в середине пурпурного */
context2=PdDupOffscreenContext(context1,0);
if (context2==NULL)
{
/* Ошибка */
}
olddc=PhDCSetCurrent(context2);
PgSetFillColor(Pg_WHITE);
PgDrawIRect(9,9,89,89,Pg_DRAW_FILL);
PgFlush();
PhDCSetCurrent(olddc);
/* Копируем в экранную область пурпурный прямоугольник, изображение которого
сформировано вне экрана в контексте 1 */
rsrc.pos.x = rdst.pos.x = rsrc.pos.y = rdst.pos.y = 0;
rsrc.size.w = rdst.size.w = rsrc.size.h = rdst.size.h = 100;
PgContextBlitArea(context1, &rsrc, NULL, &rdst);
/* Копируем пурпурный и белый прямоугольники из контекста 2
рядом с пурпурным на дисплей */
rdst.pos.x = 100;
PgContextBlitArea(context2, &rsrc, NULL, &rdst);
PgFlush();
/* Очищаем внеэкранный контекст */
PhDCRelease(context1);
PhDCRelease(context2);
context1=NULL;
context2=NULL;
Внеэкранный контекст может быть отвергнут графическим драйвером по целому ряду причин. Когда такое случается, графический драйвер отсылает менеджеру Photon'а событие Ph_EV_INFO с подтипом Ph_OFFSCREEN_INVALID. Данные этого события представляют из себя одно длинное целое, описывающее, почему внеэкранная зона была признана недействительной. Возможными причинами являются следующие:
Pg_VIDEO_MODE_SWITCHED | Графический драйвер сменил видеорежимы |
Pg_ENTERED_DIRECT | Приложение вошло в режим прямого доступа |
Pg_EXITED_DIRECT | Приложение вышло из режима прямого доступа |
Pg_DRIVER_STARTED | Видеодрайвер как раз начал выполнение |
Приложение, которое будет использовать внеэкранные контексты, должно быть чувствительным к этим событиям и соответственно реинициализировать свои внеэкранные контексты.
Внеэкранные замки
В основном Вы будете использовать внеэкранные замки с указателями, которые Вы получили от функций PdGetOffscreenContextPtr(). Замки обеспечивают, что
-
Команды потока рисования не рисуют, пока внеэкранный контекст заперт
-
Память действенна, пока приложение её использует.
Ваше приложение должно запирать внеэкранную память на как можно меньший промежуток времени. Если графическому драйверу требуется выполнить что-то с внеэкранной памятью, он пытается захватить замок себе, потенциально блокируя io-graphics на длительное время (результатом чего будет то, что экран может не обновляться, и пользователь решит, что компьютер завис).
Замки реализованы как семафоры в памяти совместного доступа между
io-graphics и приложением.
Основными шагами использования внеэкранных замков являются:
-
Создание замка для внеэкранного контекста вызовом функции PdCreateOffcreenLock(). Вы можете принять меры, чтобы, если сделан запрос на удаление внеэкранного контекста, когда он блокирован, приложению был отослан сигнал.
-
Запирание внеэкранного контекста, когда это требуется, путём вызова функции PdLockOffscreen(). Вы можете при желании задать таймаут блокирования.
-
Отпирание внеэкранного контекста путём вызова функции PdUnlockOffscreen().
-
Когда Вам больше не нужен замок внеэкранного контекста, удаление замка вызовом функции PdDestroyOffscreenLock(). Когда Вы отлаживаетесь, Вы можете вызвать функцию PdIsOffscreenLocked(), чтобы определить, заперт ли или не заперт внеэкранный контекст в настоящий момент.
Если Вы заперли контекст, вызовите функцию PdLockOffscreen(), чтобы отпереть его, перед тем, как удалить замок или освободить внеэкранный контекст.
Поддержка альфа-сопряжения
Альфа-сопряжение – это технология прорисовки прозрачности при рисовании какого-то объекта. В этой технологии комбинируется цвет рисуемого обьекта (источник) и цвет чего-то того, на чём сверху рисуется объект (получатель). Чем больше объём цвета источника, тем более непрозрачным выглядит объект.
Математически фактор смешения представляет из себя вещественное число в диапазоне от 0 до 1 включительно. В Photon микроGUI этот фактор хранится в 8 битах, т.е. масштабирован в диапазоне от 0 до 255 включительно.
32-битовый цвет создаётся из четырёх 8-битовых каналов: альфа, красный, зелёный и синий. Эти каналы представлены как (А, R, G, B). При ссылке на источник, каналы обозначаются как As, Rs, Gs и Bs; для получателя они Ad, Rd, Gd и Bd. Альфа-сопряжение примитивов драйвера поддерживает только базовое непрозрачное сопряжение с сопряжением источника:
(As, As, As, As) + ((1, 1, 1, 1) - ( As, As, As, As)).
Альфа-сопряжение может быть использовано двумя способами:
-
Как глобальный фактор, применяемый на каждый пиксель источника
или
-
С картой, указывающей альфа-сопряжение для каждого отдельного пикселя. Альфа-карта "подцеплена" к началу Вашей команды прорисовки и является "черепичной", если размеры карты меньше, чем размеры операции прорисовки.
Функции включают:
PgAlphaOff() | Выключение операций альфа-сопряжения |
PgAlphaOn() | Включение операций альфа-сопряжения |
PgAlphaValue() | Извлечение альфа-компонента из значения цвета |
PgARGB() | Преобразование значений альфа, красного, зелёного и синего в комбинированный формат цвета |
PgSetAlpha() | Детальная установка параметров альфа-сопряжения |
PgSetAlphaBlend() | Простая установка параметров альфа-сопряжения |
Поддержка хроматического ключа
Операции хроматического ключа представляют собой метод маскирования пиксельных данных при операциях формирования изображения (копирования, формирования образа, прямоугольников, прочая), основанный на значении хроматического цвета. Базовыми режимами операции являются:
-
Маскирование цвета ключа источника
-
Маскирование цвета ключа получателя
-
Маскирование всего, кроме цвета ключа источника
-
Маскирование всего, кроме цвета ключа получателя
Функции включают:
PgChromaOff() | Выключение операций хроматического ключа |
PgChromaOn() | Включение операций хроматического ключа |
PgSetChroma() | Установка хроматического ключа и операции |
Операции расширенного растра
МикроGUI Photon'а поддерживает 256 растровых операций. Операции могут быть выполнены с использованием пиксельных данных источника, пиксельных данных получателя и пиксельных данных цветного расширения монохромного шаблона. Операции расширенного растра устанавливаются тем же образом, как и обычные растровые операции, используя функцию PgSetDrawMode().
Расширенные растровые операции являются распространяющимися, что означает, что они действуют на все последующие операции прорисовки, включая операции блитирования бита (? bit-blit operations) и образы. Старый стиль растровых операций ещё существует, и его поведение такое же, как и в более поздних версиях микроGUI Photon'а.
Расширенные растровые операции определены как Pg_DrawModecharacters, в обратной записи, где characters выбирается из следующих символов:
Символ: | Означает: |
P | Pattern – шаблон |
S | Source – источник |
D | Destination – получатель |
o | OR – логическое ИЛИ |
a | AND – логическое И |
n | NOT – логическое отрицание |
x | XOR – логическое исключающее ИЛИ |
Например:
Pg_DrawModeS | Копировать все данные источника |
Pg_DrawModePSo | Логическое ИЛИ данных источника с данными шаблона |
Полный список всех доступныхх растровых операций см. в <photon/Pg.h>.
Вот такой же код:
PdOffscreenContext_t *context1;
PhRect_t rsrc,rdst;
/* Инициализация внеэкранной области и формирование данных по изображению,
которое мы хотим в ней иметь */
...
/* Копирование образа, хранящегося во внеэкранном контексте, на экран,
применение орерации OR к данным источника и шаблона вместе */
rsrc.ul.x = rdst.ul.x = rsrc.ul.y = rdst.ul.y = 0;
rsrc.lr.x = rdst.lr.x = rsrc.lr.y = rdst.lr.y = 100;
PgSetDrawMode(Pg_DrawModePSo);
PgSetFillDither(Pg_BLUE,Pg_BLACK,Pg_PAT_CHECKB8);
PgContextBlit(context1, &rsrc, NULL, &rdst);
/* Применение операции OR к шаблону в виде синией и чёрной шахматки –
и к данным источника; копирование результата на экран */
PgFlush();
Видеорежимы
Видеорежим определяет, как выглядит экран (что Вы видите на мониторе). Описание режима включает:
Width | Ширина экрана в пикселях |
Heigth | Высота экрана в пикселях |
Pixel depth | "Глубина" пикселя – число бит представляющих пиксель. определяет, как много уникальных цветов Вы можете видеть на экране одновременно. |
Refresh rate | Частота обновления кадров – число, указывающее, с какой частотой обновляется люминофор на ЭЛТ Вашего монитора (представлен в Hz). |
Метод перечисления видеорежимов, применяемый в микроGUI Photon'а, схож со спецификацией VESA, где имеются "номера режимов" – численные представления ширины, высоты и пиксельной глубины видеорежима. Частота регенерации зависит от номера режима (это является отдельным членом в PgDisplaySettings_t). Номера режимов определяет драйвер, так что для одной видеокарты режим 640х480х8 может быть режимом 2, тогда как для другой – режимом 3022. Чтобы определить свойства какого-либо данного номера режима, используйте функцию PgGetVideoModeInfo(). Чтобы получить список номеров режимов, поддерживаемых конкретным графическим драйвером, используйте функцию PgGetVideoModeList().
Функциями для работы с видеорежимами являются:
PdSetTargetDevice() | Установить целевое устройство |
PgGetGraphicsHWCaps() | Определить характеристики аппаратного обеспечения |
PgGetVideoMode() | Получить текущий видеорежим |
PgGetVideoModeInfo() | Получить информацию о видеорежиме |
PgGetVideoModeList() | Запросить у графического драйвера список поддерживаемых им видеорежимов |
PgSetVideoMode() | Установить текущий видеорежим |
Вот некий простой код:
PgVideoModes_t ModeList;
PgVideoModeInfo_t ModeInfo;
PgDisplaySettings_t ModeSetting;
int I = 0, done = 0;
if (PgGetVideoModeList(&ModeList)) {
/* Ошибка – драйвер этого не поддерживает */
}
/* Использовать для этого режима принятую по умолчанию частоту обновления */
ModeSetting.refresh = 0;