home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / divestuf.zip / DIVESTUF.TXT
Text File  |  1995-04-19  |  18KB  |  401 lines

  1.  
  2.  
  3.  
  4.   TAKING A DIVE
  5.   _____________
  6.  
  7.   Software motion video implementation under OS/2 has attained
  8.   sizable performance advantages by enabling video decompressors to
  9.   directly write to video memory.  While this technique provides good
  10.   performance, it has the disadvantage that each decompressor must
  11.   deal with the pel format of the display in various modes, clipping
  12.   the output to visible regions, and any scaling that is to be
  13.   performed. Additionally, on bank-switched video displays, the
  14.   decompressor must return on partial frames to enable the video
  15.   stream handler to switch banks.
  16.  
  17.   The Direct Interface Video Extensions (DIVE) consolidate the
  18.   complexities of dealing with direct video frame buffer access
  19.   (sometimes referred to as "direct access" or "black hole") into a
  20.   single API DLL that enables efficient transfer to video memory with
  21.   clipping, scaling, and color space conversion.  The optimized
  22.   screen access functionality provided by DIVE can be used for motion
  23.   video display, fast image updates for interactive games, and fast
  24.   screen display by 3-D graphics libraries.
  25.  
  26.  
  27.   ALL ABOUT DIVE
  28.   ______________
  29.  
  30.   DIVE is a DLL that provides optimized blitting performance for
  31.   motion video subsystems and applications that perform rapid screen
  32.   updates in the OS/2 PM and full-screen environments.  Using DIVE
  33.   functions, applications can either write directly to video memory
  34.   or use the DIVE blitter to get a high level of screen update
  35.   performance, image scaling, color space conversion, and bank-switch
  36.   display support.  The DIVE blitter utilizes acceleration hardware
  37.   when present and applicable to the function being performed.
  38.  
  39.  
  40.   DIVE DISPLAY ENGINE FUNCTION CHARACTERISTICS
  41.   ____________________________________________
  42.  
  43.   The DIVE system-level interface abstracts the low-level device
  44.   driver DIVE interface to a higher level and adds software emulation
  45.   for operations that all DIVE users have had to do.  This
  46.   system-level interface is referred to as the DIVE engine.
  47.  
  48.   The DIVE engine consists of a single, stand-alone DLL that exports
  49.   the following functions:
  50.  
  51.    o  Query for display capabilities
  52.    o  Open instance
  53.    o  Visible region specification
  54.    o  Allocation of image data buffers
  55.    o  Buffer-to-screen/buffer-to-buffer transfer (blitter) setup
  56.    o  8-bit CLUT color palette simulation/specification
  57.    o  Transfer buffer to image display/transfer buffer to buffer
  58.    o  Utility functions useful for direct access, including
  59.       window starting-address calculation
  60.    o  Frame buffer acquire/de-acquire
  61.    o  VRAM bank selection (for bank-switched displays)
  62.    o  Close instance
  63.  
  64.   The display engine enables subsystem components (for example, video
  65.   CODECs) and applications to either directly access the video buffer
  66.   or to use the display engine screen transfer functions.  If direct
  67.   access is used, the using component or application is responsible
  68.   for writing to the frame buffer format for the current display mode
  69.   and correctly clipping the output.  In addition, the component is
  70.   responsible for acquiring and bank switching the display apertures.
  71.   If display engine screen transfer functions are used, the display
  72.   engine handles clipping, pel format and color space conversions,
  73.   and any necessary hardware serialization.  The input formats and
  74.   their corresponding color encoding specification values are:
  75.  
  76.    o  CLUT 8 (256 color) - "LUT8"
  77.    o  8-bit greyscale - "GREY"
  78.    o  RGB 16 (5-6-5, 5-5-5) - "R565", "R555", "R664"
  79.    o  RGB 24 (R-G-B, B-G-R) - "RGB3", "BGR3"
  80.    o  RGB 32 (R-G-B, B-G-R) - "RGB4", "BGR4"
  81.    o  YUV 9 - DVI/Indeo three-plane color subsampled - "YUV9"
  82.    o  YUV 411 - "YUV411"
  83.    o  YUV 422 -  "YUV422"
  84.    o  YUV CCIR601 - three-plane 2x2 color subsampled (MJPEG,
  85.       MPEG) - "Y2X2"
  86.    o  YUV CCIR601 - three-plane 4x4 color subsampled  - "Y4X4"
  87.  
  88.   The output formats are:
  89.  
  90.    o  CLUT 8 (256 color)
  91.    o  RGB 16 (5-6-5, 5-5-5, 6-6-4)
  92.    o  RGB 24 (R-G-B, B-G-R)
  93.    o  RGB 32 (R-G-B-x,  B-G-R-x)
  94.    o  Blitter Operation
  95.  
  96.   There are two main ways to use DIVE:  using the DIVE blitter and
  97.   using direct-frame buffer access.  DIVE applications gain access to
  98.   DIVE functions by obtaining a DIVE handle:
  99.  
  100.         ULONG       ulErrorCode;
  101.         HDIVE       *phDiveInst;
  102.         BOOL        fNonScreenInstance;
  103.         PPVOID      ppFrameBuffer;
  104.  
  105.         ulErrorCode = DiveOpen( *phDiveInst, fNonScreenInstance, ppFrameBuffer );
  106.  
  107.   A corresponding DiveClose function must be called at application
  108.   termination.  If DIVE is to be used for blitting to the screen, set
  109.   fNonScreenInstance to FALSE.  Otherwise, if DIVE is to be used only
  110.   for off-screen sizing or color format conversion, set
  111.   fNonScreenInstance to TRUE.  If fNonScreenInstance is FALSE, a
  112.   pointer to the frame buffer is returned in ppFrameBuffer.
  113.  
  114.  
  115.   DIVE IMAGE BUFFER
  116.   _________________
  117.  
  118.   Because DIVE will use off-screen VRAM where available for
  119.   acceleration of blitting operations, the application should
  120.   allocate all source blitting buffers from DIVE whenever possible.
  121.   To allocate a buffer, the application would make the following
  122.   call:
  123.  
  124.  
  125.         ULONG   ulBufNum;
  126.         FOURCC  fccColorSpace;
  127.         ULONG   ulWidth, ulHeight, ulLineSizeBytes;
  128.         PBYTE   pbImageBuffer;
  129.  
  130.         ulErrorCode = DiveAllocImageBuffer(
  131.                 hDive,                   /* DIVE handle             */
  132.                 &ulBufNum,               /* Buffer number (output)  */
  133.                 fccColorSpace,           /* Color format            */
  134.                 ulWidth, ulHeight,       /* Size of maximum image   */
  135.                 ulLineSizeBytes,
  136.                 &pbImageBuffer);
  137.  
  138.   A corresponding DiveFreeImageBuffer function call is used to
  139.   deallocate the buffer when it is no longer needed.  The color
  140.   format of the image buffer is described by fccColorSpace.  The DIVE
  141.   interface defines constants for a variety of 8-, 16-, and 24-bit
  142.   color encoding schemes.  After a buffer is allocated and before it
  143.   can be used for blitting, it must be accessed as shown in the
  144.   following example:
  145.  
  146.         PBYTE   pbImageBuffer;
  147.         ULONG   ulBufferScanLineBytes, ulBufferScanLines;
  148.  
  149.         ulErrorCode = DiveBeginImageBufferAccess(
  150.                 hDiveInst,                /* DIVE handle                  */
  151.                 ulBufferNumber,           /* Buffer number                */
  152.                 &pbImageBuffer,           /* Ptr to image buffer (output) */
  153.                 &ulBufferScanLineBytes);  /* Scan line length (output)    */
  154.                 &ulBufferScanLines);      /* Scan lines (output)          */
  155.  
  156.   DIVE calculates the number of bytes per scan line for the image
  157.   buffer (based on the color format) and returns the value in
  158.   ulBufferScanLineBytes.  The application can now write color data
  159.   into pbImageBuffer.  For example, the application could open a
  160.   bit-map file and read the bit-map data directly into the image
  161.   buffer.  After the data has been written, the application calls
  162.   DiveEndImageBufferAccess to deaccess the buffer.  Be sure to use
  163.   scan line bytes (you might have to read a line at a time).
  164.  
  165.  
  166.   DIVE PALETTE
  167.   ____________
  168.  
  169.   Applications must inform DIVE of the state of the physical palette
  170.   upon initialization and whenever the physical palette changes.  At
  171.   application initialization, and in response to a WM_REALIZEPALETTE
  172.   message, the application calls the following sequence:
  173.  
  174.  
  175.         BYTE       pbPal■1024δ;
  176.  
  177.         /* Query the physical palette from PM   */
  178.         GpiQueryRealColors( hps, 0, 0, 256, (PLONG)pbPal);
  179.  
  180.         /* Pass it to DIVE                      */
  181.         DiveSetDestinationPalette( hDive, (PBYTE)pbPal);
  182.  
  183.  
  184.   If the application itself is using palettes, these palettes must
  185.   also be communicated to DIVE through the DiveSetSourcePalette
  186.   function. For example, if the application is using DIVE to blit
  187.   256-color palettized images to the screen, the application must
  188.   send the image palette with a call to DiveSetSourcePalette.  If a
  189.   sequence of images is being used for animation and the palette
  190.   remains constant through the series, it is necessary to call
  191.   DiveSetSourcePalette only once before blitting the first image in
  192.   the series.
  193.  
  194.   DIVE provides high-speed screen updates by bypassing PM.  In order
  195.   to maintain the integrity of the PM desktop, DIVE applications must
  196.   notify DIVE whenever the visible region of the application window
  197.   changes so that output may be clipped accordingly.
  198.  
  199.   Every DIVE application will request visible region notification at
  200.   window initialization time with the following call:
  201.  
  202.         WinSetVisibleRegionNotify( hwnd, TRUE);
  203.  
  204.   The first parameter is the handle of the window where the graphics
  205.   operations will appear, and the second parameter turns on
  206.   notification for that window.  (A corresponding
  207.   WinSetVisibleRegionNotify(hwnd, FALSE) call should be made to turn
  208.   notification off at window termination time.)
  209.  
  210.   Whenever the window's visible region begins to change, either
  211.   because the window is being moved or sized or another window or
  212.   icon overlaying the window is being moved or sized, the window will
  213.   receive a WM_VRNDISABLED message.  In response to this message,
  214.   the DIVE application will call DiveSetupBlitter (hDiveInst, 0).
  215.   After the movement is complete, the window will receive a
  216.   WM_VRNENABLED message.  In response to this message, the DIVE
  217.   application will query the new visible region, using
  218.   WinQueryVisibleRegion as follows:
  219.  
  220.         hps = WinGetPS( hwnd );
  221.         hrgn = GpiCreateRegion( hps, 0, NULL);
  222.         WinQueryVisibleRegion( hwnd, hrgn);
  223.  
  224.   Whenever the visible region, source color format, or image source
  225.   or destination size changes, the DIVE application must pass the
  226.   changes to DIVE with a call to DiveSetupBlitter.  Note that it is
  227.   necessary to pass the rectangles for the region in window
  228.   coordinates and the position of the window in desktop coordinates.
  229.  
  230.   First, get the rectangles and window coordinates:
  231.  
  232.         RECTL   rctls■50δ;      /* Rectangles for visible rgn   */
  233.         RGNRECT rgnCtl;         /* Region control struct        */
  234.         SETUP_BLITTER   SetupBlitter;   /* DiveSetupBlitter struct      */
  235.         POINTL  pointl;
  236.         SWP     swp;
  237.         HPS     hps;
  238.         HRGN    hrgn;
  239.  
  240.         rgnCtl.ircStart = 0;    /* Enumerate rectangles */
  241.         rgnCtl.crc = 50;        /* Starting with first  */
  242.         rgnCtl.ulDirection = RECTDIR_LFRT_TOPBOT;
  243.  
  244.         /* Get rectangles for the visible region        */
  245.         GpiQueryRegionRects( hps, hrgn, NULL, &rgnCtl, rctls);
  246.  
  247.         /* Find the window position relative to its parent.     */
  248.         WinQueryWindowPos( hwnd, &swp );
  249.  
  250.         /* Map window position to the desktop.  */
  251.         pointl.x = swp.x;
  252.         pointl.y = swp.y;
  253.         WinMapWindowPoints( WinQueryWindow( hwnd, QW_PARENT ),
  254.                 HWND_DESKTOP, &pointl, 1);
  255.  
  256.   Then, pass the information to DIVE:
  257.  
  258.         /* Tell DIVE about the new settings.  */
  259.         SIZEL   sizlSrcImg;     /* Size of source image */
  260.         FOURCC  fccSrcColors;   /* Source image format  */
  261.  
  262.         SetupBlitter.ulStructLen = sizeof ( SETUP_BLITTER );
  263.         SetupBlitter.fInvert = 0;
  264.         SetupBlitter.fccSrcColorFormat = fccSrcColors;
  265.         SetupBlitter.ulSrcLineSizeBytes = ulScanLineBytes;
  266.         SetupBlitter.ulSrcWidth = sizlSrcImg.cx;
  267.         SetupBlitter.ulSrcHeight = sizlSrcImg.cy;
  268.         SetupBlitter.ulSrcPosX = 0;
  269.         SetupBlitter.ulSrcPosY = 0;
  270.         SetupBlitter.fccDstColorFormat = FOURCC_SCRN;
  271.         SetupBlitter.ulDstLineSizeBytes = 0;
  272.         SetupBlitter.ulDstWidth = swp.cx;
  273.         SetupBlitter.ulDstHeight = swp.cy;
  274.         SetupBlitter.ulDstPosX = 0;
  275.         SetupBlitter.ulDstPosY = 0;
  276.         SetupBlitter.lScreenPosX = pointl.x;
  277.         SetupBlitter.lScreenPosY = pointl.y;
  278.         SetupBlitter.ulNumDstRects = rgnCtl.crcReturned;
  279.         SetupBlitter.pVisDstRects = rctls;
  280.         DiveSetupBlitter ( hDive, &SetupBlitter );
  281.  
  282.   The color format of the source image is described by fccSrcColors.
  283.  
  284.   Note that, in this example, the DIVE blitter is set up to blit to
  285.   the screen, but that need not be the case.  DIVE could also be used
  286.   to perform color conversion and/or stretch blitting to a
  287.   destination image.  The destination color-encoding format would be
  288.   indicated in fccDstColorFormat; ulDstWidth and ulDstHeight would be
  289.   set to the size of the destination image; ulNumDstRects would be
  290.   set to 1; and pVisDstRects would point to a single rectangle with
  291.   xLeft=yBottom=0 xRight=ulDstWidth and yTop=ulDstHeight.
  292.  
  293.  
  294.   DIRECT FRAME-BUFFER ACCESS
  295.   __________________________
  296.  
  297.   As mentioned earlier, *ppFrameBuffer returned by DiveOpen gives
  298.   direct addressability to the frame buffer.  In order to write
  299.   directly to the frame buffer, the DIVE application must perform its
  300.   own clipping, color conversion, and bank switching. The following
  301.   functions are provided for direct-frame buffer access:
  302.  
  303.    o  DiveAcquireFrameBuffer
  304.    o  DiveDeacquireFrameBuffer
  305.    o  DiveSwitchBank
  306.    o  DiveCalcFrameBufferAddress
  307.  
  308.   The DiveQueryCaps function returns whether the display subsystem is
  309.   bank-switched. DIVE provides another function called
  310.   DiveCalcFrameBufferAddress to get to a location in the frame buffer
  311.   that corresponds to a rectangle in desktop  coordinates:
  312.  
  313.         PRECTL prectlDest;           /* Image rectangle in desktop coors  */
  314.         PVOID pDestinationAddress;   /* Frame buffer address - output     */
  315.         PULONG pulBankNumber;        /* Display h/w bank number - output  */
  316.         PULONG pulRemlinesInBank;    /* Lines left in bank - output       */
  317.  
  318.         ulErrorCode = DiveCalcFrameBufferAddress(
  319.                 hDiveInst, &prectlDest, &pDestinationAddress,
  320.                 &pulBankNumber, &pulRemlinesInBank);
  321.  
  322.   To accomplish correct clipping, prectlDest must be in the
  323.   application window's visible region.  If the display hardware is
  324.   bank-switched, then the application must not write more than
  325.   pulRemlinesInBank lines of output before switching banks.  The data
  326.   written to pDestinationAddress must be in the color-encoding scheme
  327.   of the screen (also provided by DiveQueryCaps).  (Of course, DIVE
  328.   can be used to convert to the correct screen color-encoding prior
  329.   to writing to the frame buffer by doing a DiveBlitImage to a
  330.   destination buffer with the same color-encoding.)  Additionally, if
  331.   the screen supports only 256 colors, the data must match the
  332.   current physical palette.
  333.  
  334.   All write access to the frame buffer must be bracketed by calls to
  335.   DiveAcquireFrameBuffer and DiveDeacquireFrameBuffer.  Also, the
  336.   application must not attempt to access the frame buffer between
  337.   receipt of a WM_VRNDISABLED message and a WM_VRNENABLED message.
  338.  
  339.   This method works only on even bank breaks; indirect access through
  340.   Dive BlitImage is recommended on displays with bank breaks that are
  341.   not aligned on scan-line boundaries.
  342.  
  343.   In the next example, the application spins off a separate thread to
  344.   perform blitting.  The procedure for this thread contains a nested
  345.   loop that switches display banks for each image blitted as long as
  346.   blitting is needed.  The flag fFBAccessOK is turned off when ever
  347.   the application window received WM_VRNDISABLED and is turned on
  348.   whenever WM_VRNENABLED is received.
  349.  
  350.   A typical application would do the following:
  351.  
  352.  
  353.         BOOL  fKeepBlitting = TRUE;
  354.         BOOL  fFBAccessOK;
  355.         RECTL rectlOutput;           /* Image rectangle in desktop coors  */
  356.         RECTL rectlDest;             /* Portion to blit in this bank      */
  357.         ULONG ulMoreLines;           /* Lines in image left to blit       */
  358.         LONG  lBlitTop;              /* Top of next blit                  */
  359.         PVOID pDestinationAddress;   /* Frame buffer address - output     */
  360.         ULONG ulBankNumber;          /* Display h/w bank number - output  */
  361.         ULONG ulRemlinesInAperature; /* Lines left in bank - output       */
  362.         BOOL  fAcquired = FALSE;     /* Acquired frame buffer yet         */
  363.  
  364.         while (fKeepBlitting)
  365.           {
  366.           /* ... Call DiveSetupBlitter as before ...    */
  367.  
  368.           /********************************************************/
  369.           /* Calculate total number of lines to blit.  Then blit  */
  370.           /* only those lines that will fit in the current bank.  */
  371.           /* Switch to successive banks until the entire image is */
  372.           /* blitted.                                             */
  373.           /********************************************************/
  374.           ulMoreLines = rectlDest.yTop - rectlDest.yBottom;
  375.           memcpy( &rectlDest, &rectlOutput, sizeof(RECTL));
  376.           while (ulMoreLines && fFBAccessOK)
  377.             {
  378.             ulErrorCode = DiveCalcFrameBufferAddress(
  379.                 hDive, rectlDest, &pDestinationAddress,
  380.                 &ulBankNumber, &ulRemlinesInAperture);
  381.             if (!fAcquired)
  382.               if (!DiveAcquireFrameBuffer( hDive, ulBankNumber))
  383.                 fAcquired = TRUE;
  384.               else break;
  385.             DiveSwitchBank( hDive, ulBankNumber);
  386.               {
  387.               /* ... write data for (ulRemlinesInAperture) top lines of */
  388.               /* rectlDest to pDestinationAddress ...   */
  389.               if (ulRemlinesInAperture < ulMoreLines)
  390.                 {               /* if need next bank    */
  391.                 rectlDest.yTop -= ulRemlinesInAperture;
  392.                 ulMoreLines -= ulRemlinesInAperture;
  393.                 }
  394.               else ulMoreLines = 0;
  395.               }
  396.             if (fAcquired)
  397.               DiveDeacquireFrameBuffer( hDive);
  398.             }           /* end: while more lines to blit */
  399.           }             /* end: blitter loop    */
  400.  
  401.