home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / FOXBEAR / GFX.C < prev    next >
C/C++ Source or Header  |  1996-08-28  |  15KB  |  603 lines

  1. /*==========================================================================
  2.  *
  3.  *  Copyright (C) 1995-1996 Microsoft Corporation. All Rights Reserved.
  4.  *  Copyright (C) 1994-1995 ATI Technologies Inc. All Rights Reserved.
  5.  *
  6.  *  File:       gfx.c
  7.  *  Content:    graphics API
  8.  *
  9.  ***************************************************************************/
  10. #include "foxbear.h"
  11.  
  12. GFX_BITMAP  *lpVRAM;
  13.  
  14. static BOOL fForceRestore = FALSE;
  15.  
  16. /*
  17.  * gfxBlt
  18.  */
  19. BOOL gfxBlt(RECT *dst, GFX_HBM bm, POINT *src)
  20. {
  21.     GFX_BITMAP* pbm = (GFX_BITMAP*)bm;
  22.     HRESULT     ddrval;
  23.     DWORD       bltflags;
  24.     RECT        rc;
  25.     int         x,y,dx,dy;
  26.  
  27.     if( GameSize.cy == C_SCREEN_H )
  28.     {
  29.         x         = dst->left;
  30.         y         = dst->top;
  31.         dx        = dst->right  - dst->left;
  32.         dy        = dst->bottom - dst->top;
  33.         rc.left   = src->x;
  34.         rc.top    = src->y;
  35.         rc.right  = rc.left + dx;
  36.         rc.bottom = rc.top  + dy;
  37.     }
  38.     else
  39.     {
  40.         x         = MapX(dst->left);
  41.         y         = MapY(dst->top);
  42.         dx        = MapX(dst->right) - x;
  43.         dy        = MapY(dst->bottom) - y;
  44.         rc.left   = MapDX(src->x);
  45.         rc.top    = MapDY(src->y);
  46.         rc.right  = rc.left + dx;
  47.         rc.bottom = rc.top  + dy;
  48.     }
  49.  
  50.     if( dx == 0 || dy == 0 )
  51.     {
  52.         return TRUE;
  53.     }
  54.  
  55.     if (pbm->lpSurface)
  56.     {
  57.         if( pbm->bTrans )
  58.             bltflags = bTransDest ? DDBLTFAST_DESTCOLORKEY : DDBLTFAST_SRCCOLORKEY;
  59.         else
  60.             bltflags = bTransDest ? DDBLTFAST_DESTCOLORKEY : DDBLTFAST_NOCOLORKEY;
  61.  
  62.         ddrval = IDirectDrawSurface_BltFast(
  63.                         lpBackBuffer, x, y,
  64.                         pbm->lpSurface, &rc, bltflags | DDBLTFAST_WAIT);
  65.  
  66.         if (ddrval != DD_OK)
  67.         {
  68.             Msg("BltFast failed err=%d", ddrval);
  69.         }
  70.     }
  71.     else
  72.     {
  73.         DDBLTFX     ddbltfx;
  74.  
  75.         rc.left   = x;
  76.         rc.top    = y;
  77.         rc.right  = rc.left + dx;
  78.         rc.bottom = rc.top  + dy;
  79.  
  80.         ddbltfx.dwSize = sizeof( ddbltfx );
  81.         ddbltfx.dwFillColor = pbm->dwColor;
  82.  
  83.         ddrval = IDirectDrawSurface_Blt(
  84.                         lpBackBuffer,           // dest surface
  85.                         &rc,                    // dest rect
  86.                         NULL,                   // src surface
  87.                         NULL,                   // src rect
  88.                         DDBLT_COLORFILL | DDBLT_WAIT,
  89.                         &ddbltfx);
  90.     }
  91.  
  92.     return TRUE;
  93.  
  94. } /* gfxBlt */
  95.  
  96. /*
  97.  * gfxCreateSolidColorBitmap
  98.  */
  99. GFX_HBM gfxCreateSolidColorBitmap(COLORREF rgb)
  100. {
  101.     GFX_BITMAP *pvram;
  102.  
  103.     pvram = MemAlloc( sizeof( *pvram ) );
  104.  
  105.     if( pvram == NULL )
  106.     {
  107.         return NULL;
  108.     }
  109.  
  110.     pvram->dwColor = DDColorMatch(lpBackBuffer, rgb);
  111.     pvram->lpSurface = NULL;
  112.     pvram->lpbi = NULL;
  113.     pvram->bTrans = FALSE;
  114.  
  115.     pvram->link = lpVRAM;
  116.     lpVRAM = pvram;
  117.  
  118.     return (GFX_HBM) pvram;
  119.  
  120. } /* gfxCreateSolidColorBitmap */
  121.  
  122. /*
  123.  * gfxCreateBitmap
  124.  */
  125. GFX_HBM gfxCreateVramBitmap(BITMAPINFOHEADER UNALIGNED *lpbi,BOOL bTrans)
  126. {
  127.     GFX_BITMAP *pvram;
  128.  
  129.     pvram = MemAlloc( sizeof( *pvram ) );
  130.  
  131.     if( pvram == NULL )
  132.     {
  133.         return NULL;
  134.     }
  135.     pvram->lpSurface = DDCreateSurface(MapRX(lpbi->biWidth),
  136.                                        MapRY(lpbi->biHeight), FALSE, TRUE);
  137.     pvram->lpbi = lpbi;
  138.     pvram->dwColor = 0;
  139.     pvram->bTrans = bTrans;
  140.  
  141.     if( pvram->lpSurface == NULL )
  142.     {
  143.         return NULL;
  144.     }
  145.  
  146.     pvram->link = lpVRAM;
  147.     lpVRAM = pvram;
  148.     gfxRestore((GFX_HBM) pvram);
  149.  
  150.     return (GFX_HBM) pvram;
  151.  
  152. } /* gfxCreateVramBitmap */
  153.  
  154. /*
  155.  * gfxDestroyBitmap
  156.  */
  157. BOOL gfxDestroyBitmap ( GFX_HBM hbm )
  158. {
  159.     GFX_BITMAP *p = (GFX_BITMAP *)hbm;
  160.  
  161.     if (hbm == NULL || hbm == GFX_TRUE)
  162.     {
  163.         return FALSE;
  164.     }
  165.  
  166.     if (p->lpSurface)
  167.     {
  168.         IDirectDrawSurface_Release(p->lpSurface);
  169.         p->lpSurface = NULL;
  170.     }
  171.  
  172.     if (p->lpbi)
  173.     {
  174.         p->lpbi = NULL;
  175.     }
  176.  
  177.     MemFree((VOID *)p);
  178.  
  179.     return TRUE;
  180.  
  181. } /* gfxDestroyBitmap */
  182.  
  183. /*
  184.  * gfxStretchBackBuffer()
  185.  */
  186. BOOL gfxStretchBackbuffer()
  187. {
  188.     if (lpStretchBuffer)
  189.     {
  190.         IDirectDrawSurface_Blt(
  191.                             lpStretchBuffer,        // dest surface
  192.                             NULL,                   // dest rect (all of it)
  193.                             lpBackBuffer,           // src surface
  194.                             &GameRect,              // src rect
  195.                             DDBLT_WAIT,
  196.                             NULL);
  197.  
  198.         IDirectDrawSurface_Blt(
  199.                             lpBackBuffer,           // dest surface
  200.                             NULL,                   // dest rect (all of it)
  201.                             lpStretchBuffer,        // src surface
  202.                             NULL,                   // src rect
  203.                             DDBLT_WAIT,
  204.                             NULL);
  205.     }
  206.     else
  207.     {
  208.         IDirectDrawSurface_Blt(
  209.                         lpBackBuffer,           // dest surface
  210.                         NULL,                   // dest rect (all of it)
  211.                         lpBackBuffer,           // src surface
  212.                         &GameRect,              // src rect
  213.                         DDBLT_WAIT,
  214.                         NULL);
  215.     }
  216.  
  217.     return TRUE;
  218.  
  219. } /* gfxStretchBackbuffer */
  220.  
  221. /*
  222.  * gfxFlip
  223.  */
  224. BOOL gfxFlip( void )
  225. {
  226.     HRESULT     ddrval;
  227.  
  228.     ddrval = IDirectDrawSurface_Flip( lpFrontBuffer, NULL, DDFLIP_WAIT );
  229.     if( ddrval != DD_OK )
  230.     {
  231.         Msg( "Flip FAILED, rc=%08lx", ddrval );
  232.         return FALSE;
  233.     }
  234.     return TRUE;
  235.  
  236. } /* gfxFlip */
  237.  
  238. /*
  239.  * gfxUpdateWindow
  240.  */
  241. BOOL gfxUpdateWindow()
  242. {
  243.     HRESULT     ddrval;
  244.  
  245.     ddrval = IDirectDrawSurface_Blt(
  246.                     lpFrontBuffer,          // dest surface
  247.                     &rcWindow,              // dest rect
  248.                     lpBackBuffer,           // src surface
  249.                     NULL,                   // src rect (all of it)
  250.                     DDBLT_WAIT,
  251.                     NULL);
  252.  
  253.     return ddrval == DD_OK;
  254.  
  255. } /* gfxUpdateWindow */
  256.  
  257. /*
  258.  * gfxSwapBuffers
  259.  *
  260.  * this is called when the game loop has rendered a frame into
  261.  * the backbuffer, its goal is to display something for the user to see.
  262.  *
  263.  * there are four cases...
  264.  *
  265.  * Fullscreen:
  266.  *      we just call IDirectDrawSurface::Flip(lpFrontBuffer)
  267.  *      being careful to handle return code right.
  268.  *
  269.  * Fullscreen (stretched):
  270.  *      the game loop has rendered a frame 1/2 the display
  271.  *      size, we do a Blt to stretch the frame to the backbuffer
  272.  *      the we just call IDirectDrawSurface::Flip(lpFrontBuffer)
  273.  *
  274.  * Window mode (foreground palette):
  275.  *      in this case we call IDirectDrawSurface::Blt to copy
  276.  *      the back buffer to the window.
  277.  *
  278.  * Window mode (background palette):
  279.  *      in this case we are in a window, but we dont own the
  280.  *      palette. all our art was loaded to a specific palette
  281.  *      IDirectDrawSurface::Blt does not do color translation
  282.  *      we have a few options in this case...
  283.  *
  284.  *          reload or remap the art to the the current palette
  285.  *          (we can do this easily with a GetDC, StetchDIBits)
  286.  *          FoxBear has *alot* of art, so this would be too slow.
  287.  *
  288.  *          use GDI to draw the backbuffer, GDI will handle
  289.  *          the color conversion so things will look correct.
  290.  *
  291.  *          pause the game (this is what we do so this function
  292.  *          will never be called)
  293.  *
  294.  */
  295. BOOL gfxSwapBuffers( void )
  296. {
  297.     if( bFullscreen )
  298.     {
  299.         if( bStretch )
  300.         {
  301.             gfxStretchBackbuffer();
  302.         }
  303.  
  304.         if (nBufferCount > 1)
  305.             return gfxFlip();
  306.         else
  307.             return TRUE;
  308.     }
  309.     else
  310.     {
  311.         return gfxUpdateWindow();
  312.     }
  313.  
  314. } /* gfxSwapBuffers */
  315.  
  316. /*
  317.  * gfxBegin
  318.  */
  319. GFX_HBM gfxBegin( void )
  320. {
  321.     if( !DDEnable() )
  322.     {
  323.         return NULL;
  324.     }
  325.  
  326.     if( !DDCreateFlippingSurface() )
  327.     {
  328.         DDDisable(TRUE);
  329.         return NULL;
  330.     }
  331.     Splash();
  332.  
  333.     return GFX_TRUE;
  334.  
  335. } /* gfxBegin */
  336.  
  337. /*
  338.  * gfxEnd
  339.  */
  340. BOOL gfxEnd ( GFX_HBM hbm )
  341. {
  342.     GFX_BITMAP  *curr;
  343.     GFX_BITMAP  *next;
  344.  
  345.     for( curr = lpVRAM; curr; curr=next )
  346.     {
  347.         next = curr->link;
  348.         gfxDestroyBitmap ((GFX_HBM)curr);
  349.     }
  350.  
  351.     lpVRAM = NULL;
  352.  
  353.     return DDDisable(FALSE);
  354.  
  355.     return TRUE;
  356.  
  357. } /* gfxEnd */
  358.  
  359. /*
  360.  * gfxRestore
  361.  *
  362.  * restore the art when one or more surfaces are lost
  363.  */
  364. BOOL gfxRestore(GFX_HBM bm)
  365. {
  366.     GFX_BITMAP *pbm = (GFX_BITMAP*)bm;
  367.     HRESULT     ddrval;
  368.     HDC hdc;
  369.     LPVOID lpBits;
  370.     RGBQUAD *prgb;
  371.     int i,w,h;
  372.     RECT rc;
  373.  
  374.     struct {
  375.         BITMAPINFOHEADER bi;
  376.         RGBQUAD          ct[256];
  377.     }   dib;
  378.  
  379.     IDirectDrawSurface *pdds = pbm->lpSurface;
  380.     BITMAPINFOHEADER   UNALIGNED *pbi  = pbm->lpbi;
  381.  
  382.     if (pdds == NULL)
  383.         return TRUE;
  384.  
  385.     if (IDirectDrawSurface_Restore(pdds) != DD_OK)
  386.         return FALSE;
  387.  
  388.     if (pbi == NULL)
  389.         return TRUE;
  390.  
  391.     //
  392.     // in 8bbp mode if we get switched away from while loading
  393.     // (and palette mapping) our art, the colors will not be correct
  394.     // because some app may have changed the system palette.
  395.     //
  396.     // if we are in stress mode, just keep going.  It is more important
  397.     // to make progress than to get the colors right.
  398.     //
  399.  
  400.     if (!bFullscreen &&
  401.          GameBPP == 8 && 
  402.          GetForegroundWindow() != hWndMain && 
  403.          !bStress )
  404.     {
  405.         Msg("gfxRestore: **** foreground window changed while loading art!");
  406.         fForceRestore = TRUE;
  407.         PauseGame();
  408.         return FALSE;
  409.     }
  410.  
  411.     dib.bi = *pbi;
  412.  
  413.     prgb = (RGBQUAD *)((LPBYTE)pbi + pbi->biSize);
  414.     lpBits = (LPBYTE)(prgb + pbi->biClrUsed);
  415.  
  416.     if( pbi->biClrUsed == 0 && pbi->biBitCount <= 8 )
  417.     {
  418.         lpBits = (LPBYTE)(prgb + (1<<pbi->biBitCount));
  419.     }
  420.  
  421.     w = MapRX(pbi->biWidth);
  422.     h = MapRY(pbi->biHeight);
  423.     /*
  424.      * hack to make sure fox off-white doesn't become
  425.      * pure white (which is transparent)
  426.      */
  427.     for( i=0; i<256; i++ )
  428.     {
  429.         dib.ct[i] = prgb[i];
  430.  
  431.         if( dib.ct[i].rgbRed   == 0xff &&
  432.             dib.ct[i].rgbGreen == 0xff &&
  433.             dib.ct[i].rgbBlue  == 224 )
  434.         {
  435.             dib.ct[i].rgbBlue = 0x80;
  436.         }
  437.         else
  438.         if( dib.ct[i].rgbRed   == 251 &&
  439.             dib.ct[i].rgbGreen == 243 &&
  440.             dib.ct[i].rgbBlue  == 234 )
  441.         {
  442.             dib.ct[i].rgbBlue = 0x80;
  443.         }
  444.     }
  445.  
  446.     /*
  447.      * if we are in 8bit mode we know the palette is 332 we can
  448.      * do the mapping our self.
  449.      *
  450.      * NOTE we can only do this in fullscreen mode
  451.      * in windowed mode, we have to share the palette with
  452.      * the window manager and we dont get all of the colors
  453.      * in the order we assume.
  454.      *
  455.      */
  456.     if (bFullscreen && GameBPP == pbi->biBitCount && GameBPP == 8 )
  457.     {
  458.         BYTE xlat332[256];
  459.         DDSURFACEDESC ddsd;
  460.         int x,y,dib_pitch;
  461.         BYTE *src, *dst;
  462.         BOOL stretch;
  463.         IDirectDrawSurface *pdds1;
  464.         HDC hdc1;
  465.  
  466.         stretch = w != pbi->biWidth || h != pbi->biHeight;
  467.  
  468.         for( i=0;i<256;i++ )
  469.         {
  470.             xlat332[i] =
  471.                 ((dib.ct[i].rgbRed   >> 0) & 0xE0 ) |
  472.                 ((dib.ct[i].rgbGreen >> 3) & 0x1C ) |
  473.                 ((dib.ct[i].rgbBlue  >> 6) & 0x03 );
  474.         }
  475.  
  476.         /*
  477.          * if we are stretching copy into the back buffer
  478.          * then use GDI to stretch later.
  479.          */
  480.         if( stretch )
  481.         {
  482.             pdds1 = lpBackBuffer;
  483.         }
  484.         else
  485.         {
  486.             pdds1 = pdds;
  487.         }
  488.  
  489.         ddsd.dwSize = sizeof(ddsd);
  490.         ddrval = IDirectDrawSurface_Lock(
  491.             pdds1, NULL, &ddsd, DDLOCK_WAIT, NULL);
  492.  
  493.         if( ddrval == DD_OK )
  494.         {
  495.             dib_pitch = (pbi->biWidth+3)&~3;
  496.             src = (BYTE *)lpBits + dib_pitch * (pbi->biHeight-1);
  497.             dst = (BYTE *)ddsd.lpSurface;
  498.             for( y=0; y<(int)pbi->biHeight; y++ )
  499.             {
  500.                 for( x=0; x<(int)pbi->biWidth; x++ )
  501.                 {
  502.                     dst[x] = xlat332[src[x]];
  503.                 }
  504.                 dst += ddsd.lPitch;
  505.                 src -= dib_pitch;
  506.             }
  507.             IDirectDrawSurface_Unlock(pdds1, NULL);
  508.         }
  509.         else
  510.         {
  511.             Msg("Lock failed err=%d", ddrval);
  512.             return FALSE;
  513.         }
  514.  
  515.         if( stretch )
  516.         {
  517.             if( IDirectDrawSurface_GetDC(pdds,&hdc) == DD_OK )
  518.             {
  519.                 if( IDirectDrawSurface_GetDC(pdds1,&hdc1) == DD_OK )
  520.                 {
  521.                     SetStretchBltMode(hdc, COLORONCOLOR);
  522.                     StretchBlt(hdc, 0, 0, w, h,
  523.                         hdc1, 0, 0, pbi->biWidth, pbi->biHeight, SRCCOPY);
  524.                     IDirectDrawSurface_ReleaseDC(pdds1,hdc1);
  525.                 }
  526.                 IDirectDrawSurface_ReleaseDC(pdds,hdc);
  527.             }
  528.         }
  529.     }
  530.     else if( IDirectDrawSurface_GetDC(pdds,&hdc) == DD_OK )
  531.     {
  532.         SetStretchBltMode(hdc, COLORONCOLOR);
  533.         StretchDIBits(hdc, 0, 0, w, h,
  534.             0, 0, pbi->biWidth, pbi->biHeight,
  535.             lpBits, (BITMAPINFO *)&dib.bi, DIB_RGB_COLORS, SRCCOPY);
  536.  
  537.         IDirectDrawSurface_ReleaseDC(pdds,hdc);
  538.     }
  539.  
  540.     /*
  541.      * show the art while loading...
  542.      */
  543.     rc.left = rcWindow.left,
  544.     rc.top  = rcWindow.top + 20;
  545.     rc.right = rc.left + w;
  546.     rc.bottom = rc.top + h;
  547.     IDirectDrawSurface_Blt(lpFrontBuffer, &rc, pdds, NULL, DDBLT_WAIT, NULL);
  548.  
  549.     return TRUE;
  550.  
  551. } /* gfxRestore */
  552.  
  553. /*
  554.  * gfxRestoreAll
  555.  *
  556.  * restore the art when one or more surfaces are lost
  557.  */
  558. BOOL gfxRestoreAll()
  559. {
  560.     GFX_BITMAP  *curr;
  561.     HWND hwndF = GetForegroundWindow();
  562.  
  563.     Splash();
  564.  
  565.     for( curr = lpVRAM; curr != NULL; curr = curr->link)
  566.     {
  567.         if (curr->lpSurface &&
  568.             (fForceRestore || IDirectDrawSurface_IsLost(curr->lpSurface) == DDERR_SURFACELOST))
  569.         {
  570.             if( !gfxRestore(curr) )
  571.             {
  572.                 Msg( "gfxRestoreAll: ************ Restore FAILED!" );
  573.                 return FALSE;
  574.             }
  575.         }
  576.     }
  577.  
  578.     DDClear();
  579.     fForceRestore = FALSE;
  580.     return TRUE;
  581.  
  582. } /* gfxRestoreAll */
  583.  
  584. /*
  585.  * gfxFillBack
  586.  */
  587. void gfxFillBack( DWORD dwColor )
  588. {
  589.     DDBLTFX     ddbltfx;
  590.  
  591.     ddbltfx.dwSize = sizeof( ddbltfx );
  592.     ddbltfx.dwFillColor = dwColor;
  593.  
  594.     IDirectDrawSurface_Blt(
  595.                         lpBackBuffer,           // dest surface
  596.                         NULL,                   // dest rect
  597.                         NULL,                   // src surface
  598.                         NULL,                   // src rect
  599.                         DDBLT_COLORFILL | DDBLT_WAIT,
  600.                         &ddbltfx);
  601.  
  602. } /* gfxFillBack */
  603.