|
Обновите ArcaOS до уровня NeoWPS
- Установите набор PNG иконок, нарисованных дизайнером, специализирующемся на оформлении OS/2
- Установите eSchemes 2018, чтобы менять цвета и кнопки на рабочем столе
|
Применение DIVE для создания графических приложений |
TITLE: Применение DIVE для создания графических приложений
DATE: 2002-02-04 12:19:52
AUTHOR: Artem Davidenko
DIVE (Direct Interface Video Extensions) был разработан
для скоростного доступа к видео буферу. В своем API имеет функции для "прозрачной"
организации клиппирования вывода, скаллинга и конверсии глубины цвета.
DIVE оптимизирован для вывода потокового видео и использования в играх.
Может задействовать, при наличии, 2D функции видео-ускорителя для повышения
скорости вывода.
Динамически линкуемая библиотека DIVE экспортирует
следующие функции:
- Запрос параметров текущего видеорежима
- Инициализация и деинициализация DIVE
- Спецификации видимого региона
- Определения видео буфера
- Установки буфер-буфер или буфер-экран трансфера (посредством блиттера)
- Симуляции восьмибитовой палитры
- Функции применяемые для прямого доступа, включая функция вычисления стартового адреса окна
- Функции переключения банков (для banked-режимов)
Входные форматы:
- CLUT 8 (256 color) - "LUT8"
- 8-bit grayscale - "GREY"
- RGB 16 (5-6-5, 5-5-5) - "R565", "R555", "R664"
- RGB 24 (R-G-B, B-G-R) - "RGB3", "BGR3"
- RGB 32 (R-G-B, B-G-R) - "RGB4", "BGR4"
- YUV 9 - DVI/Indeo three-plane color subsampled - "YUV9"
- YUV 411 - "YUV411"
- YUV 422 - "YUV422"
- YUV CCIR601 - three-plane 2x2 color subsampled (MJPEG, MPEG) - "Y2X2"
- YUV CCIR601 - three-plane 4x4 color subsampled? - "Y4X4"
Выходные форматы:
- CLUT 8 (256 цветов)
- RGB 16 (5-6-5, 5-5-5, 6-6-4)
- RGB 24 (R-G-B, B-G-R)
- RGB 32 (R-G-B-x,? B-G-R-x)
- Blitter Operation
Существует два пути использования DIVE: применение DIVE-блиттера
и прямой доступ к буферу. Следующая последовательность инициализирует DIVE
и возвращает DIVE handle:
ULONG ulErrorCode;
HDIVE *phDiveInst;
BOOL fNonScreenInstance;
PPVOID ppFrameBuffer;
ulErrorCode = DiveOpen(*phDiveInst, fNonScreenInstance, ppFrameBuffer);
Функция DiveClose должна быть вызвана по окончании работы
приложения.
Если DIVE использует блиттинг в видео-буфер, то fNonScreenInstance
должна быть установлена в FALSE, иначе, если DIVE используется только для
конверсии глубины цвета или изменения размера буфера без вывода на экран
fNonScreenInstance = TRUE. Чтобы DIVE мог использовать функции 2D ускорителя
для операций вывода буфера, он должен быть определен при помощи DiveAllocImageBuffer.
Следующий фрагмент показывает как это сделать:
ULONG ulBufNum;
FOURCC fccColorSpace;
ULONG ulWidth, ulHeight, ulLineSizeBytes;
PBYTE pbImageBuffer;
ulErrorCode = DiveAllocImageBuffer
(
hDive, /* DIVE хэндл */
&ulBufNum, /* Номер буфера */
fccColorSpace, /* Формат */
ulWidth, ulHeight, /* Максимальный размер изображения */
ulLineSizeBytes,
&pbImageBuffer
);
После того как буфер определен, перед записью в него
необходимо вызвать функцию DiveBeginImageBufferAccess так, как это показано
в следующем примере:
PBYTE pbImageBuffer;
ULONG ulBufferScanLineBytes, ulBufferScanLines;
ulErrorCode = DiveBeginImageBufferAccess
(
hDiveInst, /* DIVE хэндл */
ulBufferNumber, /* Номер буфера */
&pbImageBuffer, /* Указатель на буфер */
&ulBufferScanLineBytes, /* Размер линии в байтах */
&ulBufferScanLines /* Всего линий */
);
DIVE вычисляет количество байт на одну линию буфера
и возвращает значение в ulBufferScanLineBytes. Далее приложение может проводить
запись данных в pbImageBuffer. После того как данные были записаны, приложение
должно вызвать DiveEndImageBufferAccess.
Приложение должно информировать DIVE о состоянии
физической палитры во время его инициализации и при каждой смене палитры.
Для инициализации приложения и при полученном сообщении WM_REALIZEPALETTE
должна вызываться следующая последовательность:
BYTE pbPal 1024;
/* Запрос текущей физической палитры у Presentation Manager */
GpiQueryRealColors(hps, 0, 0, 256, (PLONG)pbPal);
/* Установка ее как целевой палитры в DIVE */
DiveSetDestinationPalette(hDive, (PBYTE)pbPal);
Если приложение само использует палитру (например, для
вывода палитрового изображения на экран), она должна быть сообщена DIVE
посредством DiveSetSourcePalette. Если предполагается вывод серии изображений
в одной палитре, то вызов функции необходим только перед выводом первого
изображения.
DIVE обеспечивает высокоскоростное обновления экрана
в обход Presentation Manager. Для нормальной работы совместно с PM десктопом,
DIVE приложение должно сообщать DIVE об изменениях видимого региона окна
приложения, что-бы обеспечить таким образом клиппирование.
Каждое DIVE приложение во время инициализации должно
устанавливать нотификацию видимого региона следующим вызовом:
WinSetVisibleRegionNotify(hwnd, TRUE);
Первый параметр суть хэндл окна где производятся графические
операции, второй - включает нотификацию для этого окна. По окончании работы
приложения, должна вызываться функция:
WinSetVisibleRegionNotify(hwnd, FALSE);
для выключения нотификации.
При изменении видимого региона окна, например, когда оно
было перенесено или был изменен его размер или другое окно или иконка перекрыли
его при перенесении или изменении размера, окно получает сообщение WM_VRNDISABLED.
В ответ на это сообщение DIVE приложение должно вызвать
DiveSetupBlitter(hDiveInst, 0);
После того как перемещение окончено, окно получает сообщение WM_VRNENABLED.
Следующим шагом должен следовать запрос нового видимого региона, посредством
функции WinQueryVisibleRegion:
hps = WinGetPS(hwnd);
hrgn = GpiCreateRegion(hps, 0, NULL);
WinQueryVisibleRegion(hwnd, hrgn);
Функция DiveSetupBlitter должна вызываться всякий раз
при изменениях видимого региона, глубины цвета, размеров исходного и целевого
изображений. Это должно выглядеть примерно так:
RECTL rctls;
RGNRECT rgnCtl;
SETUP_BLITTER SetupBlitter;
POINTL pointl;
SWP swp;
HPS hps;
HRGN hrgn;
rgnCtl.ircStart = 0;
rgnCtl.crc = 50;
rgnCtl.ulDirection = RECTDIR_LFRT_TOPBOT;
/* Получение видимого региона */
GpiQueryRegionRects(hps, hrgn, NULL, &rgnCtl, rctls);
/* Получение позиции текущего окна относительно родительского. */
WinQueryWindowPos( hwnd, &swp );
/* Маппинг позиции окна на десктоп */
pointl.x = swp.x;
pointl.y = swp.y;
WinMapWindowPoints(WinQueryWindow(hwnd, QW_PARENT),
HWND_DESKTOP, &pointl, 1);
/* Сообщить информацию о новых установках в DIVE */
SIZEL sizlSrcImg; /* Размер исходного изображения */
FOURCC fccSrcColors /* Формат */
SetupBlitter.ulStructLen = sizeof (SETUP_BLITTER);
SetupBlitter.fInvert = 0;
SetupBlitter.fccSrcColorFormat = fccSrcColors;
SetupBlitter.ulSrcLineSizeBytes = ulScanLineBytes;
SetupBlitter.ulSrcWidth = sizlSrcImg.cx;
SetupBlitter.ulSrcHeight = sizlSrcImg.cy;
SetupBlitter.ulSrcPosX = 0;
SetupBlitter.ulSrcPosY = 0;
SetupBlitter.fccDstColorFormat = FOURCC_SCRN;
SetupBlitter.ulDstLineSizeBytes = 0;
SetupBlitter.ulDstWidth = swp.cx;
SetupBlitter.ulDstHeight = swp.cy;
SetupBlitter.ulDstPosX = 0;
SetupBlitter.ulDstPosY = 0;
SetupBlitter.lScreenPosX = pointl.x;
SetupBlitter.lScreenPosY = pointl.y;
SetupBlitter.ulNumDstRects = rgnCtl.crcReturned;
SetupBlitter.pVisDstRects = rctls;
DiveSetupBlitter (hDive, &SetupBlitter);
Формат цвета исходного изображения описывается посредством
fccSrcColors.
В приведенном выше примере, DIVE блиттер устанавливается
для вывода в видеобуфер. Но это не единственный вариант использования блиттера.
Он может применяться так-же для конверсии глубины цвета или изменения размера
с выводом в другой буфер. Целевой формат цвета должен быть установлен в
fccDstColorFormat. ulDstWidth и ulDstHeight должны указывать новый размер
изображения, ulNumDstRects должен быть равен 1 и pVisDstRects должен указывать
на область с xLeft = yBottom = 0, xRight = ulDstWidth и yTop = ulDstHeight.
Как упоминалось ранее, *ppFrameBuffer возвращаемая
DiveOpen служит для прямой адресации к видео-буферу. Этот метод доступа
предполагает, что приложение будет само организовывать клиппирование, конверсию
цвета и переключение банков. Функции необходимые для прямого доступа:
- DiveAcquireFrameBuffer
- DiveDeacquireFrameBuffer
- DiveSwitchBank
- DiveCalcFrameBufferAddress
Функция DiveQueryCaps используется для получения информации
о нахождении видео подсистемы в banked режиме. DiveCalcFrameBufferAddress
получает линейный адрес буфера.
PRECTL prectlDest; /* Координаты в десктопе */
PVOID pDestinationAddress; /* Адрес буфера */
PULONG pulBankNumber; /* Номер банка */
PULONG pulRemlinesInBank; /* Линии, оставшиеся в банке */
ulErrorCode = DiveCalcFrameBufferAddress
(
hDiveInst, &prectlDest, &pDestinationAddress,
&pulBankNumber, &pulRemlinesInBank
);
Для выполнения корректного клиппирования prectlDest должен находиться внутри
видимой области окна приложения. Если текущий видео режим требует переключения
банков, то приложение не должно выводить больше чем pulRemlinesInBank линий
для каждого банка. Данные выводимые в pDestinationAddress должны быть того
же формата что и видео-буфер(см. DiveQueryCaps) (Для приведения их к этому
виду можно использовать все тот же DIVE). Плюс к тому, если текущий режим
является палитровым, то данные должны соответствовать физической палитре.
Все записи в буфер должны начинаться с DiveAcquireFrameBuffer и заканчиваться
DiveDeacquireFrameBuffer. Кроме того приложение не должно получать доступа
к видео-буферу между сообщениями WM_VRNDISABLED и WM_VRNENABLED. Следующий
фрагмент представляет прямой вывод видео-буфер при разбиении на банки.
Флаг fFBAccessOK снимается когда приложение получает сообщение WM_VRNDISABLED
и устанавливается при сообщении WM_VRNENABLED.
BOOL fKeepBlitting = TRUE;
BOOL fFBAccessOK;
RECTL rectlOutput;
RECTL rectlDest;
ULONG ulMoreLines;
LONG lBlitTop;
PVOID pDestinationAddress;
ULONG ulBankNumber;
ULONG ulRemlinesInAperature;
BOOL fAcquired = FALSE;
while (fKeepBlitting)
{
/* ... здесь вызов DiveSetupBlitter как и раньше ... */
/********************************************************/
/* Вычисление количества линий для вывода. Вывод только */
/* тех линий которые находятся в текущем банке */
/* Переключение банков пока все изображение не будет */
/* выведено. */
/********************************************************/
ulMoreLines = rectlDest.yTop - rectlDest.yBottom;
memcpy(&rectlDest, &rectlOutput, sizeof(RECTL));
while (ulMoreLines && fFBAccessOK)
{
ulErrorCode = DiveCalcFrameBufferAddress
(
hDive, rectlDest, &pDestinationAddress,
&ulBankNumber, &ulRemlinesInAperture
);
if (!fAcquired)
if (!DiveAcquireFrameBuffer(hDive, ulBankNumber))
fAcquired = TRUE;
else break;
DiveSwitchBank(hDive, ulBankNumber);
{
if (ulRemlinesInAperture < ulMoreLines)
{
rectlDest.yTop -= ulRemlinesInAperture;
ulMoreLines -= ulRemlinesInAperture;
}
else ulMoreLines = 0;
}
if (fAcquired)
DiveDeacquireFrameBuffer(hDive);
} /* end: пока есть линии для вывода */
} /* end: цикл вывода */
Пара советов:
- Прежде всего, если это возможно, сразу определится с глубиной цвета.
- Пускать блиттер лучше (читай правильнее) в отдельной нити.
- Почитать про DIVE можно в тулките - book/mmref2.inf
- Примеры все в том-же тулките - samples/mm/dive/ и /samples/mm/fsdive/
- Очень неплохая статья
Дмитрия Завалишина помогает понять идеологию программирования под /2 (и в частности графики).
- Так-же полезно поинтересоваться RDM2.
Здесь вы можете посмотреть на примеры использования DIVE
Простенькая демка и ее аналог для dos'a (необходим
какой-нибудь dpmi сервер (os/2 в качестве сервера подойдет:)) |
|
|
моя версия "the Matrix" :) |
ксоникс, еще в процессе разработки. |
|
- Артем Давиденко aka sNOa aka 2:5036/12.777
P.S.
По сути эта статья является переводом divestuff.zip, добытого с CD06.
P.P.S.
greetings всем маньякам которые верят в то что у /2 есть будущее.
всем кто живет на #os2russian
e-Deniska и e-co за периодическое пинание на подвиги
Lelik - WarpVision просто класс
[zuko] - ты уже перестал пить коньяк по утрам (отвечай да/нет)
nickk - в частности за новый mkisofs
RElf - за множество полезной информации
Комментарии: Validator 2002-02-04 16:00:00 | Насчет "радужная" - специфика сайта обязывает :-). А демы у мя на Warp4+XRRM15+14.082c+SDD b44 - без проблем. Кстати смотрятся кульно. Тока я не понял, пачяму в матрице иероглифы? |-) | sNOa 2002-02-04 17:33:34 | вообще там не иероглифы, а японский шрифт(специально для этого часами медитировал перед скриншутом с фильма). все писалось на ACP2+SDD b43. | Сергей 2002-02-04 17:44:35 | 2sNOa: А еще какие-нибудь проги есть? Игра какая-нибудь маленькая, но прикольная? | Sergey Posokhov 2002-02-04 18:49:19 | Bugs, выпускаемая когда-то Стардоком.
Летит такая чушка и стреляет жуков!!!
Для детей от 5 до 8 подойдет :-) | zuko 2002-02-04 20:05:44 | sNOa: да/нет | sNOa 2002-02-04 21:28:57 | 2zuko: кааайф.
2Сергей: проги-то есть а вот с графикой грабли.
из меня то художник еще тот :(
| Max Droganow 2002-02-05 09:48:34 | Чнго- ты про графику-то плачешься ??? Нарисую что надо - ты ИДЕИ дава-а-а-а-й.... (рисовать буду пока с плюсами не разберусь - тады уж ты мне рисовать будешь ;-))))) ) | Max Droganow 2002-02-05 09:50:31 | И вообще - пора симулятор алкоголиков писать... (PSSST-4 ZX Speccy) | RElf 2002-02-05 11:16:29 | А помните мы тут с Леликом баг в DIVE зафиксили:
Fix for DIVE.DLL to allow hicolor. Look for 0BC0C745F000 and replace the latest 00 with 01. Don't forget to unpack by lxLite before!
| SERG 2002-02-05 11:57:07 | Какой симулятор алкаголиков.
АРКАНОИД хочу чем не идея.
Даже полвовина графического материала есть например в игре xonex. | Eugene Gorbunoff 2002-02-05 13:13:02 | Сделайте гаму про БиллаГейтса. Что-нибудь типа "Захват главного офиса Микрософт". | Eugene 2002-02-05 14:28:15 | Из FAQ по фильму "Матрица":
Q: Что это за зеленого цвета в коде Матрицы?
A: Это числа и зеркально отраженные японские буквы алфавита катакана.
| sNOa 2002-02-05 14:58:02 | eros2: спасибо, учту.
RElf: таки да, жить стало лучше, жить стало веселей(отфикшенный дайв буду подкладывать в архивы).
ppl: а кто укажет на точный алгоритм этого эффекта.
| Max Droganow 2002-02-07 12:11:18 | Про Билли идеи сразу отметаются. Этот главный телепузик сам подохнет ... а симулятор алкоголиков - давно вынашиваемая идея - довольно проста в реализации, но играбелна до жути... | Олег Булаский 2002-02-11 07:19:45 | А нельзя Matrix переделать как модуль к скринсейверу, а?
Очень хоцца... | sNOa 2002-02-12 22:14:04 | 2 Олег Булаский: а к какому ссэйверу? | RElf 2002-02-13 04:35:31 | Как я понял, имеется ввиду
[url]
ErOS2 сделал несколько DIVE модулей к нему, включая мою адаптацию IFSIM2. Их можно найти на его странице [url]
Так что, можно к нему обращаться за консультацией.
| ErOs2 2002-02-13 14:35:13 | Можно обращатся. Только моя страница счас в дауне. Скринсейверные модули которые я делал работают с ScreenSaver (by Зигфрид Ханиш) и Blanker. Модули есть на хоббесе.
| Deniska 2002-02-13 15:15:15 | а отдельными exe их можно получить? а то ставить это чудо не хочется, а тот же IFSIM - очень красивая штука. | ErOs2 2002-02-13 17:19:42 | to Deniska: пока нет. | Олег Булаский 2002-03-04 07:16:36 | to ErOs2 & sNOa: блин, мужики, ну сделайте "матрицу" к скринсеверу...
| sNOa 2002-03-04 18:45:52 | хыхы, ленимся мы:) пока | LightElf 2002-03-16 10:31:02 | Хотелось бы остановиться на двух моментах:
1. Наличие аппаратной акселерации можно определить (в какой-то степени) по порядку следования элементов в списке поодерживаемых входных форматов, который возвращает функция DiveQueryCaps. Если аппаратной поддержки нет, то первым (наиболее предпочтительным с точки зрения DIVE) будет FOURCC_R565. При наличии в системе аппаратного акселератора первыми в списке будут форматы, поддерживаемые акселератором. Это может быть полезно для тех, кто пишет разнообразные видеоплейеры.
2. При наличии аппаратной акселерации, буфер выделяемый по DiveAllocImageBuffer реально располагается в видеопамяти со всеми вытекающими последствиями (видеопамять не кэшируется на чтение и вообще, чтение оттуда очень медленное), так что в этот буфер надо только писать и как можно более быстро. |
Прокомментируйте эту статью (напоминаем, автор работал над текстом несколько недель, уважайте мнение других).
|
|
Готовая eComStation на SSD диске
Последний активный опрос: Какая высота барьера RPM?
[Google]
|
IBM OS/2 Warp
|