Руководство программиста в Photon (953920), страница 50
Текст из файла (страница 50)
Вам нет необходимости находится в режиме прямого доступа, чтобы получить указатель на внеэкранную память, но надо находиться в нём, чтобы получить указатель на основной дисплей. Вот некий псевдокод:
/* Создание контекста прямого доступа */
direct_context = PdCreateDirectContext();
/* Запуск режима прямого доступа */
PdDirectStart(direct_context);
/* Получение основного дисплея */
primary_display = PdCreateOffscreenContext( 0, 0, 0, Pg_OSC_MAIN_DISPLAY);
/* Получение указателя на дисплей */
vidptr = PdGetOffscreenContextPtr(primary_display);
/* Убеждаемся, что драйвер Photon'а ничего не делает
(этого не может быть в данной точке, но мы просто убеждаемся, что
у нас нет продвинутости движка прорисовки видеокарты)
(??? it shouldn't be at this point but this is just to
be sure that we haven't gotten ahead of the video card's draw engine). */
PgWaitHWIdle();
/* Делаем то, что мы делаем в памяти */
Do_something(vidptr);
/* Выход из режима прямого доступа, и удаление контекста прямого доступа
(альтернативой может быть функция PdDirectStop(),
если мы не хотим уничтожать контекст*/
PdReleaseDirectContext(direct_mode);
Внеэкранная видеопамять
Эти вызовы программного интерфейса приложения позволяют Вам использовать остаточную (leftover) память видеокарты. Когда видеокарта находится в видеорежиме, это обычно остаток видеопамяти, который не используется областью дисплея. Эти области памяти могут использоваться для выполнения различных графических операций, хотя используются ещё акселератором видеокарты. В микроGUI Photon'а они в основном рассматриваются в качестве возможности, аналогичной использованию контекста памяти, но их использование будет более быстрым, поскольку для этих областей имеется аппаратное ускорение. Функции и структуры данных включают:
PdCreateOffscreenContext() | Создание внеэкранного контекста в видеопамяти |
PdDupOffscreenContext() | Дублирование внеэкранного контекста |
PdGetOffscreenContextPtr() | Создание ссылки на объект совместно используемой памяти внеэкранного контекста |
PdOffscreenContext_t | Структура данных, описывающая внеэкранный контекст |
PdSetOffscreenTranslation() | Установка преобразования для внеэкранного контекста |
PdSetTargetDevice() | Установка целевого устройства |
PgContextBlit() | Копирование данных из прямоугольника в одном контексте в другой контекст |
PgContextBlitArea() | Копирование данных из области в одном контексте в другой контекст |
PgSwapDisplay() | Указать ЭЛТ видеодисплея на заданный контекст |
PgWaitHWIdle() | Ожидать, пока видеодрайвер не окажется в простое |
PhDCRelease() | Освобождение контекста прорисовки |
Вот некий простой код, который создаёт и формирует изображение во внеэкранном буфере, а затем копирует данные на экран. Он создаёт два внеэкранных контекста объёмом 100х100, выполняет какую-то прорисовку, блитинг, и затем блитирует результат в текущую область (т.е. в область, принадлежащую PtWindow). В этом примере предполагается, что Вы уже создали окно и вызвали функцию PgSetRegion(), чтобы указать, что область окна вызывает появление событий прорисовки:
#include <Pt.h>
PtInit( NULL );
/* ... */
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;