GFX.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:15k
源码类别:

Windows编程

开发平台:

Visual C++

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