Reviews / articles about OS/2 |
Operating systems: ArcaOS, eComStation, IBM OS/2 Warp |
|
|
DATE: 2002-02-04 12:19:52 AUTHOR: Artem Davidenko
DIVE (Direct Interface Video Extensions) был разработан для скоростного доступа к видео буферу. В своем API имеет функции для "прозрачной" организации клиппирования вывода, скаллинга и конверсии глубины цвета. DIVE оптимизирован для вывода потокового видео и использования в играх. Может задействовать, при наличии, 2D функции видео-ускорителя для повышения скорости вывода. Динамически линкуемая библиотека DIVE экспортирует следующие функции:
Входные форматы:
Выходные форматы:
Существует два пути использования 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 служит для прямой адресации к видео-буферу. Этот метод доступа предполагает, что приложение будет само организовывать клиппирование, конверсию цвета и переключение банков. Функции необходимые для прямого доступа:
Функция 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
- Артем Давиденко 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 - за множество полезной информации
Комментарии:
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(C) OS2.GURU 2001-2021