Руководство программиста в 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;















