home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 24
/
CD_ASCQ_24_0995.iso
/
vrac
/
divestuf.zip
/
DIVESTUF.TXT
next >
Wrap
Text File
|
1995-04-19
|
18KB
|
401 lines
TAKING A DIVE
_____________
Software motion video implementation under OS/2 has attained
sizable performance advantages by enabling video decompressors to
directly write to video memory. While this technique provides good
performance, it has the disadvantage that each decompressor must
deal with the pel format of the display in various modes, clipping
the output to visible regions, and any scaling that is to be
performed. Additionally, on bank-switched video displays, the
decompressor must return on partial frames to enable the video
stream handler to switch banks.
The Direct Interface Video Extensions (DIVE) consolidate the
complexities of dealing with direct video frame buffer access
(sometimes referred to as "direct access" or "black hole") into a
single API DLL that enables efficient transfer to video memory with
clipping, scaling, and color space conversion. The optimized
screen access functionality provided by DIVE can be used for motion
video display, fast image updates for interactive games, and fast
screen display by 3-D graphics libraries.
ALL ABOUT DIVE
______________
DIVE is a DLL that provides optimized blitting performance for
motion video subsystems and applications that perform rapid screen
updates in the OS/2 PM and full-screen environments. Using DIVE
functions, applications can either write directly to video memory
or use the DIVE blitter to get a high level of screen update
performance, image scaling, color space conversion, and bank-switch
display support. The DIVE blitter utilizes acceleration hardware
when present and applicable to the function being performed.
DIVE DISPLAY ENGINE FUNCTION CHARACTERISTICS
____________________________________________
The DIVE system-level interface abstracts the low-level device
driver DIVE interface to a higher level and adds software emulation
for operations that all DIVE users have had to do. This
system-level interface is referred to as the DIVE engine.
The DIVE engine consists of a single, stand-alone DLL that exports
the following functions:
o Query for display capabilities
o Open instance
o Visible region specification
o Allocation of image data buffers
o Buffer-to-screen/buffer-to-buffer transfer (blitter) setup
o 8-bit CLUT color palette simulation/specification
o Transfer buffer to image display/transfer buffer to buffer
o Utility functions useful for direct access, including
window starting-address calculation
o Frame buffer acquire/de-acquire
o VRAM bank selection (for bank-switched displays)
o Close instance
The display engine enables subsystem components (for example, video
CODECs) and applications to either directly access the video buffer
or to use the display engine screen transfer functions. If direct
access is used, the using component or application is responsible
for writing to the frame buffer format for the current display mode
and correctly clipping the output. In addition, the component is
responsible for acquiring and bank switching the display apertures.
If display engine screen transfer functions are used, the display
engine handles clipping, pel format and color space conversions,
and any necessary hardware serialization. The input formats and
their corresponding color encoding specification values are:
o CLUT 8 (256 color) - "LUT8"
o 8-bit greyscale - "GREY"
o RGB 16 (5-6-5, 5-5-5) - "R565", "R555", "R664"
o RGB 24 (R-G-B, B-G-R) - "RGB3", "BGR3"
o RGB 32 (R-G-B, B-G-R) - "RGB4", "BGR4"
o YUV 9 - DVI/Indeo three-plane color subsampled - "YUV9"
o YUV 411 - "YUV411"
o YUV 422 - "YUV422"
o YUV CCIR601 - three-plane 2x2 color subsampled (MJPEG,
MPEG) - "Y2X2"
o YUV CCIR601 - three-plane 4x4 color subsampled - "Y4X4"
The output formats are:
o CLUT 8 (256 color)
o RGB 16 (5-6-5, 5-5-5, 6-6-4)
o RGB 24 (R-G-B, B-G-R)
o RGB 32 (R-G-B-x, B-G-R-x)
o Blitter Operation
There are two main ways to use DIVE: using the DIVE blitter and
using direct-frame buffer access. DIVE applications gain access to
DIVE functions by obtaining a DIVE handle:
ULONG ulErrorCode;
HDIVE *phDiveInst;
BOOL fNonScreenInstance;
PPVOID ppFrameBuffer;
ulErrorCode = DiveOpen( *phDiveInst, fNonScreenInstance, ppFrameBuffer );
A corresponding DiveClose function must be called at application
termination. If DIVE is to be used for blitting to the screen, set
fNonScreenInstance to FALSE. Otherwise, if DIVE is to be used only
for off-screen sizing or color format conversion, set
fNonScreenInstance to TRUE. If fNonScreenInstance is FALSE, a
pointer to the frame buffer is returned in ppFrameBuffer.
DIVE IMAGE BUFFER
_________________
Because DIVE will use off-screen VRAM where available for
acceleration of blitting operations, the application should
allocate all source blitting buffers from DIVE whenever possible.
To allocate a buffer, the application would make the following
call:
ULONG ulBufNum;
FOURCC fccColorSpace;
ULONG ulWidth, ulHeight, ulLineSizeBytes;
PBYTE pbImageBuffer;
ulErrorCode = DiveAllocImageBuffer(
hDive, /* DIVE handle */
&ulBufNum, /* Buffer number (output) */
fccColorSpace, /* Color format */
ulWidth, ulHeight, /* Size of maximum image */
ulLineSizeBytes,
&pbImageBuffer);
A corresponding DiveFreeImageBuffer function call is used to
deallocate the buffer when it is no longer needed. The color
format of the image buffer is described by fccColorSpace. The DIVE
interface defines constants for a variety of 8-, 16-, and 24-bit
color encoding schemes. After a buffer is allocated and before it
can be used for blitting, it must be accessed as shown in the
following example:
PBYTE pbImageBuffer;
ULONG ulBufferScanLineBytes, ulBufferScanLines;
ulErrorCode = DiveBeginImageBufferAccess(
hDiveInst, /* DIVE handle */
ulBufferNumber, /* Buffer number */
&pbImageBuffer, /* Ptr to image buffer (output) */
&ulBufferScanLineBytes); /* Scan line length (output) */
&ulBufferScanLines); /* Scan lines (output) */
DIVE calculates the number of bytes per scan line for the image
buffer (based on the color format) and returns the value in
ulBufferScanLineBytes. The application can now write color data
into pbImageBuffer. For example, the application could open a
bit-map file and read the bit-map data directly into the image
buffer. After the data has been written, the application calls
DiveEndImageBufferAccess to deaccess the buffer. Be sure to use
scan line bytes (you might have to read a line at a time).
DIVE PALETTE
____________
Applications must inform DIVE of the state of the physical palette
upon initialization and whenever the physical palette changes. At
application initialization, and in response to a WM_REALIZEPALETTE
message, the application calls the following sequence:
BYTE pbPal■1024δ;
/* Query the physical palette from PM */
GpiQueryRealColors( hps, 0, 0, 256, (PLONG)pbPal);
/* Pass it to DIVE */
DiveSetDestinationPalette( hDive, (PBYTE)pbPal);
If the application itself is using palettes, these palettes must
also be communicated to DIVE through the DiveSetSourcePalette
function. For example, if the application is using DIVE to blit
256-color palettized images to the screen, the application must
send the image palette with a call to DiveSetSourcePalette. If a
sequence of images is being used for animation and the palette
remains constant through the series, it is necessary to call
DiveSetSourcePalette only once before blitting the first image in
the series.
DIVE provides high-speed screen updates by bypassing PM. In order
to maintain the integrity of the PM desktop, DIVE applications must
notify DIVE whenever the visible region of the application window
changes so that output may be clipped accordingly.
Every DIVE application will request visible region notification at
window initialization time with the following call:
WinSetVisibleRegionNotify( hwnd, TRUE);
The first parameter is the handle of the window where the graphics
operations will appear, and the second parameter turns on
notification for that window. (A corresponding
WinSetVisibleRegionNotify(hwnd, FALSE) call should be made to turn
notification off at window termination time.)
Whenever the window's visible region begins to change, either
because the window is being moved or sized or another window or
icon overlaying the window is being moved or sized, the window will
receive a WM_VRNDISABLED message. In response to this message,
the DIVE application will call DiveSetupBlitter (hDiveInst, 0).
After the movement is complete, the window will receive a
WM_VRNENABLED message. In response to this message, the DIVE
application will query the new visible region, using
WinQueryVisibleRegion as follows:
hps = WinGetPS( hwnd );
hrgn = GpiCreateRegion( hps, 0, NULL);
WinQueryVisibleRegion( hwnd, hrgn);
Whenever the visible region, source color format, or image source
or destination size changes, the DIVE application must pass the
changes to DIVE with a call to DiveSetupBlitter. Note that it is
necessary to pass the rectangles for the region in window
coordinates and the position of the window in desktop coordinates.
First, get the rectangles and window coordinates:
RECTL rctls■50δ; /* Rectangles for visible rgn */
RGNRECT rgnCtl; /* Region control struct */
SETUP_BLITTER SetupBlitter; /* DiveSetupBlitter struct */
POINTL pointl;
SWP swp;
HPS hps;
HRGN hrgn;
rgnCtl.ircStart = 0; /* Enumerate rectangles */
rgnCtl.crc = 50; /* Starting with first */
rgnCtl.ulDirection = RECTDIR_LFRT_TOPBOT;
/* Get rectangles for the visible region */
GpiQueryRegionRects( hps, hrgn, NULL, &rgnCtl, rctls);
/* Find the window position relative to its parent. */
WinQueryWindowPos( hwnd, &swp );
/* Map window position to the desktop. */
pointl.x = swp.x;
pointl.y = swp.y;
WinMapWindowPoints( WinQueryWindow( hwnd, QW_PARENT ),
HWND_DESKTOP, &pointl, 1);
Then, pass the information to DIVE:
/* Tell DIVE about the new settings. */
SIZEL sizlSrcImg; /* Size of source image */
FOURCC fccSrcColors; /* Source image format */
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 );
The color format of the source image is described by fccSrcColors.
Note that, in this example, the DIVE blitter is set up to blit to
the screen, but that need not be the case. DIVE could also be used
to perform color conversion and/or stretch blitting to a
destination image. The destination color-encoding format would be
indicated in fccDstColorFormat; ulDstWidth and ulDstHeight would be
set to the size of the destination image; ulNumDstRects would be
set to 1; and pVisDstRects would point to a single rectangle with
xLeft=yBottom=0 xRight=ulDstWidth and yTop=ulDstHeight.
DIRECT FRAME-BUFFER ACCESS
__________________________
As mentioned earlier, *ppFrameBuffer returned by DiveOpen gives
direct addressability to the frame buffer. In order to write
directly to the frame buffer, the DIVE application must perform its
own clipping, color conversion, and bank switching. The following
functions are provided for direct-frame buffer access:
o DiveAcquireFrameBuffer
o DiveDeacquireFrameBuffer
o DiveSwitchBank
o DiveCalcFrameBufferAddress
The DiveQueryCaps function returns whether the display subsystem is
bank-switched. DIVE provides another function called
DiveCalcFrameBufferAddress to get to a location in the frame buffer
that corresponds to a rectangle in desktop coordinates:
PRECTL prectlDest; /* Image rectangle in desktop coors */
PVOID pDestinationAddress; /* Frame buffer address - output */
PULONG pulBankNumber; /* Display h/w bank number - output */
PULONG pulRemlinesInBank; /* Lines left in bank - output */
ulErrorCode = DiveCalcFrameBufferAddress(
hDiveInst, &prectlDest, &pDestinationAddress,
&pulBankNumber, &pulRemlinesInBank);
To accomplish correct clipping, prectlDest must be in the
application window's visible region. If the display hardware is
bank-switched, then the application must not write more than
pulRemlinesInBank lines of output before switching banks. The data
written to pDestinationAddress must be in the color-encoding scheme
of the screen (also provided by DiveQueryCaps). (Of course, DIVE
can be used to convert to the correct screen color-encoding prior
to writing to the frame buffer by doing a DiveBlitImage to a
destination buffer with the same color-encoding.) Additionally, if
the screen supports only 256 colors, the data must match the
current physical palette.
All write access to the frame buffer must be bracketed by calls to
DiveAcquireFrameBuffer and DiveDeacquireFrameBuffer. Also, the
application must not attempt to access the frame buffer between
receipt of a WM_VRNDISABLED message and a WM_VRNENABLED message.
This method works only on even bank breaks; indirect access through
Dive BlitImage is recommended on displays with bank breaks that are
not aligned on scan-line boundaries.
In the next example, the application spins off a separate thread to
perform blitting. The procedure for this thread contains a nested
loop that switches display banks for each image blitted as long as
blitting is needed. The flag fFBAccessOK is turned off when ever
the application window received WM_VRNDISABLED and is turned on
whenever WM_VRNENABLED is received.
A typical application would do the following:
BOOL fKeepBlitting = TRUE;
BOOL fFBAccessOK;
RECTL rectlOutput; /* Image rectangle in desktop coors */
RECTL rectlDest; /* Portion to blit in this bank */
ULONG ulMoreLines; /* Lines in image left to blit */
LONG lBlitTop; /* Top of next blit */
PVOID pDestinationAddress; /* Frame buffer address - output */
ULONG ulBankNumber; /* Display h/w bank number - output */
ULONG ulRemlinesInAperature; /* Lines left in bank - output */
BOOL fAcquired = FALSE; /* Acquired frame buffer yet */
while (fKeepBlitting)
{
/* ... Call DiveSetupBlitter as before ... */
/********************************************************/
/* Calculate total number of lines to blit. Then blit */
/* only those lines that will fit in the current bank. */
/* Switch to successive banks until the entire image is */
/* blitted. */
/********************************************************/
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);
{
/* ... write data for (ulRemlinesInAperture) top lines of */
/* rectlDest to pDestinationAddress ... */
if (ulRemlinesInAperture < ulMoreLines)
{ /* if need next bank */
rectlDest.yTop -= ulRemlinesInAperture;
ulMoreLines -= ulRemlinesInAperture;
}
else ulMoreLines = 0;
}
if (fAcquired)
DiveDeacquireFrameBuffer( hDive);
} /* end: while more lines to blit */
} /* end: blitter loop */