Advertisement
xiahanlu

VBA- GDI渲染转Direct3D Surface

Aug 31st, 2018
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.89 KB | None | 0 0
  1. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  2. // Copyright (C) 1999-2003 Forgotten
  3. // Copyright (C) 2004 Forgotten and the VBA development team
  4.  
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2, or(at your option)
  8. // any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software Foundation,
  17. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  
  19. #include "stdafx.h"
  20. #include <stdio.h>
  21.  
  22. #include "../System.h"
  23. #include "../GBA.h"
  24. #include "../Globals.h"
  25. #include "../Text.h"
  26.  
  27. #include "VBA.h"
  28. #include "MainWnd.h"
  29. #include "Reg.h"
  30. #include "resource.h"
  31. #include <d3d9.h>
  32. #include <assert.h>
  33.  
  34.  
  35. static IDirect3D9 *_Direct3D9_root = nullptr;
  36. static IDirect3DDevice9 *_Direct3D9_device = nullptr;   /* device object */
  37. static IDirect3DSurface9 *_Direct3D9_surface = nullptr; /* vram object */
  38. static _D3DLOCKED_RECT _Direct3D9_LockRect;
  39. static INT _scr_x;
  40. static INT _scr_y;
  41.  
  42.  
  43. #ifdef _DEBUG
  44. #define new DEBUG_NEW
  45. #undef THIS_FILE
  46. static char THIS_FILE[] = __FILE__;
  47. #endif
  48.  
  49. extern void winlog(const char *,...);
  50. extern int RGB_LOW_BITS_MASK;
  51. extern int Init_2xSaI(u32);
  52. extern int systemSpeed;
  53.  
  54. class GDIDisplay : public IDisplay {
  55. private:
  56.   u8 *filterData;
  57.   u8 info[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)];
  58.  
  59. public:
  60.   GDIDisplay();
  61.   virtual ~GDIDisplay();
  62.  
  63.   virtual bool initialize();
  64.   virtual void cleanup();
  65.   virtual void render();
  66.   virtual void checkFullScreen();
  67.   virtual void renderMenu();
  68.   virtual void clear();
  69.   virtual DISPLAY_TYPE getType() { return GDI; };
  70.   virtual void setOption(const char *, int) {}
  71.   virtual bool isSkinSupported() { return true; }
  72.   virtual int selectFullScreenMode(GUID **);
  73.   virtual bool isMoecmksHack(int w, int h) { return true; }
  74.   virtual void resetDevice(HWND window);
  75. };
  76.  
  77. static int calculateShift(u32 mask)
  78. {
  79.   int m = 0;
  80.  
  81.   while(mask) {
  82.     m++;
  83.     mask >>= 1;
  84.   }
  85.  
  86.   return m-5;
  87. }
  88.  
  89. GDIDisplay::GDIDisplay()
  90. {
  91.   filterData = (u8 *)malloc(4*4*256*(240+80));
  92. }
  93.  
  94. GDIDisplay::~GDIDisplay()
  95. {
  96.   cleanup();
  97. }
  98.  
  99. void GDIDisplay::cleanup()
  100. {
  101.   if(filterData) {
  102.     free(filterData);
  103.     filterData = NULL;
  104.   }
  105. }
  106.  
  107. bool GDIDisplay::initialize()
  108. {
  109.   theApp.sizeX = 240;
  110.   theApp.sizeY = 160;
  111.   switch(theApp.videoOption) {
  112.   case VIDEO_1X:
  113.     theApp.surfaceSizeX = theApp.sizeX;
  114.     theApp.surfaceSizeY = theApp.sizeY;
  115.     break;
  116.   case VIDEO_2X:
  117.     theApp.surfaceSizeX = theApp.sizeX * 2;
  118.     theApp.surfaceSizeY = theApp.sizeY * 2;
  119.     break;
  120.   case VIDEO_3X:
  121.     theApp.surfaceSizeX = theApp.sizeX * 3;
  122.     theApp.surfaceSizeY = theApp.sizeY * 3;
  123.     break;
  124.   case VIDEO_4X:
  125.     theApp.surfaceSizeX = theApp.sizeX * 4;
  126.     theApp.surfaceSizeY = theApp.sizeY * 4;
  127.     break;
  128.   case VIDEO_320x240:
  129.   case VIDEO_640x480:
  130.   case VIDEO_800x600:
  131.   case VIDEO_OTHER:
  132.     {
  133.       int scaleX = (theApp.fsWidth / theApp.sizeX);
  134.       int scaleY = (theApp.fsHeight / theApp.sizeY);
  135.       int min = scaleX < scaleY ? scaleX : scaleY;
  136.       if(theApp.fsMaxScale)
  137.         min = min > theApp.fsMaxScale ? theApp.fsMaxScale : min;
  138.       theApp.surfaceSizeX = theApp.sizeX * min;
  139.       theApp.surfaceSizeY = theApp.sizeY * min;
  140.       if(theApp.fullScreenStretch) {
  141.         theApp.surfaceSizeX = theApp.fsWidth;
  142.         theApp.surfaceSizeY = theApp.fsHeight;
  143.       }
  144.     }
  145.     break;
  146.   }
  147.  
  148.   theApp.rect.left = 0;
  149.   theApp.rect.top = 0;
  150.   theApp.rect.right = theApp.sizeX;
  151.   theApp.rect.bottom = theApp.sizeY;
  152.  
  153.   theApp.dest.left = 0;
  154.   theApp.dest.top = 0;
  155.   theApp.dest.right = theApp.surfaceSizeX;
  156.   theApp.dest.bottom = theApp.surfaceSizeY;
  157.  
  158.   DWORD style = WS_POPUP | WS_VISIBLE;
  159.   DWORD styleEx = 0;
  160.  
  161.   if(theApp.videoOption <= VIDEO_4X)
  162.     style |= WS_OVERLAPPEDWINDOW;
  163.   else
  164.     styleEx = 0;
  165.  
  166.   if(theApp.videoOption <= VIDEO_4X)
  167.     AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx);
  168.   else
  169.     AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx);    
  170.  
  171.   int winSizeX = theApp.dest.right-theApp.dest.left;
  172.   int winSizeY = theApp.dest.bottom-theApp.dest.top;
  173.  
  174.   if(theApp.videoOption > VIDEO_4X) {
  175.     winSizeX = theApp.fsWidth;
  176.     winSizeY = theApp.fsHeight;
  177.   }
  178.  
  179.   int x = 0;
  180.   int y = 0;
  181.  
  182.   if(theApp.videoOption <= VIDEO_4X) {
  183.     x = theApp.windowPositionX;
  184.     y = theApp.windowPositionY;
  185.   }
  186.  
  187.   // Create a window
  188.   MainWnd *pWnd = new MainWnd;
  189.   theApp.m_pMainWnd = pWnd;
  190.  
  191.   pWnd->CreateEx(styleEx,
  192.                  theApp.wndClass,
  193.                  "VisualBoyAdvance",
  194.                  style,
  195.                  x,y,winSizeX,winSizeY,
  196.                  NULL,
  197.                  0);
  198.  
  199.   if (!(HWND)*pWnd) {
  200.     winlog("Error creating Window %08x\n", GetLastError());
  201.     return FALSE;
  202.   }
  203.  
  204.   theApp.updateMenuBar();
  205.  
  206.   theApp.adjustDestRect();
  207.  
  208.   theApp.mode320Available = false;
  209.   theApp.mode640Available = false;
  210.   theApp.mode800Available = false;
  211.  
  212.   HDC dc = GetDC(NULL);
  213.   HBITMAP hbm = CreateCompatibleBitmap(dc, 1, 1);
  214.   BITMAPINFO *bi = (BITMAPINFO *)info;
  215.   ZeroMemory(bi, sizeof(info));
  216.   bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  217.   GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);  
  218.   GetDIBits(dc, hbm, 0, 1, NULL, (LPBITMAPINFO)info, DIB_RGB_COLORS);
  219.   DeleteObject(hbm);
  220.   ReleaseDC(NULL, dc);
  221.  
  222.   if(bi->bmiHeader.biCompression == BI_BITFIELDS) {
  223.     systemColorDepth = bi->bmiHeader.biBitCount;
  224.     if(systemColorDepth == 15)
  225.       systemColorDepth = 16;
  226.     systemRedShift = calculateShift(*((DWORD *)&bi->bmiColors[0]));
  227.     systemGreenShift = calculateShift(*((DWORD *)&bi->bmiColors[1]));
  228.     systemBlueShift = calculateShift(*((DWORD *)&bi->bmiColors[2]));
  229.     if(systemColorDepth == 16) {
  230.       if(systemGreenShift == 6) {
  231.         Init_2xSaI(565);
  232.         RGB_LOW_BITS_MASK=0x821;
  233.       } else {
  234.         Init_2xSaI(555);
  235.         RGB_LOW_BITS_MASK=0x421;        
  236.       }
  237.     } else if(systemColorDepth == 32)
  238.       Init_2xSaI(32);
  239.   } else {
  240.     systemColorDepth = 32;
  241.     systemRedShift = 19;
  242.     systemGreenShift = 11;
  243.     systemBlueShift = 3;
  244.  
  245.     Init_2xSaI(32);    
  246.   }
  247.   theApp.fsColorDepth = systemColorDepth;
  248.   if(systemColorDepth == 24)
  249.     theApp.filterFunction = NULL;
  250. #ifdef MMX
  251.   if(!theApp.disableMMX)
  252.     cpu_mmx = theApp.detectMMX();
  253.   else
  254.     cpu_mmx = 0;
  255. #endif
  256.  
  257.   switch(systemColorDepth) {
  258.   case 16:
  259.     {
  260.       for(int i = 0; i < 0x10000; i++) {
  261.         systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
  262.           (((i & 0x3e0) >> 5) << systemGreenShift) |
  263.           (((i & 0x7c00) >> 10) << systemBlueShift);
  264.       }
  265.     }
  266.     break;
  267.   case 24:
  268.   case 32:
  269.     {
  270.       for(int i = 0; i < 0x10000; i++) {
  271.         systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
  272.           (((i & 0x3e0) >> 5) << systemGreenShift) |
  273.           (((i & 0x7c00) >> 10) << systemBlueShift);
  274.       }      
  275.     }
  276.     break;
  277.   }
  278.   theApp.updateFilter();
  279.   theApp.updateIFB();
  280.  
  281.   pWnd->DragAcceptFiles(TRUE);
  282. #if  0
  283.   namespace _D3D_moecmks {
  284.  static IDirect3D9 *_Direct3D9_root = nullptr;
  285.  static IDirect3DDevice9 *_Direct3D9_device = nullptr;   /* device object */
  286.  static IDirect3DSurface9 *_Direct3D9_surface = nullptr; /* vram object */
  287.  static INT _scr_x;
  288.  static INT _scr_y;
  289. };
  290.  
  291. #  endif
  292.   // Create Direct3D Device
  293.   if (_Direct3D9_root == nullptr)  {
  294. #  define DIRECT3D_VERSION_ 0x900
  295.     _Direct3D9_root = Direct3DCreate9 (DIRECT3D_VERSION_);
  296.     assert (_Direct3D9_root != nullptr);
  297.  
  298.     D3DPRESENT_PARAMETERS d3dpp;
  299.     ZeroMemory (& d3dpp, sizeof (d3dpp));
  300.  
  301.     _scr_x = GetSystemMetrics (SM_CXSCREEN);
  302.     _scr_y = GetSystemMetrics (SM_CYSCREEN);
  303.  
  304.     d3dpp.BackBufferFormat      = D3DFMT_X8R8G8B8;
  305.     d3dpp.SwapEffect            = D3DSWAPEFFECT_DISCARD;
  306.     d3dpp.Flags                 = 0;
  307.     d3dpp.hDeviceWindow         = *pWnd;
  308.     d3dpp.Windowed              = TRUE;
  309.     d3dpp.BackBufferWidth       = _scr_x;
  310.     d3dpp.BackBufferHeight      = _scr_y;
  311.     d3dpp.PresentationInterval  = D3DPRESENT_INTERVAL_IMMEDIATE; /* Disable VSync */
  312.  
  313.     HRESULT sig = _Direct3D9_root->CreateDevice (0,
  314.                           D3DDEVTYPE_HAL,
  315.                              *pWnd,
  316.                                 D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, & _Direct3D9_device);
  317.     assert (SUCCEEDED (sig));
  318.  
  319.     sig = _Direct3D9_device->CreateOffscreenPlainSurface (_scr_x,
  320.           _scr_y, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM,
  321.         & _Direct3D9_surface, NULL);
  322.     assert (SUCCEEDED (sig));
  323.   }
  324.  
  325.   return TRUE;  
  326. }
  327.  
  328. void GDIDisplay::clear()
  329. {
  330. }
  331.  
  332. void GDIDisplay::renderMenu()
  333. {
  334.   checkFullScreen();
  335.   theApp.m_pMainWnd->DrawMenuBar();
  336. }
  337.  
  338. void GDIDisplay::checkFullScreen()
  339. {
  340. }
  341.  
  342. extern "C"
  343. void __cdecl bilinear (DWORD *dstPtr, intptr_t dstPitch,
  344.                       DWORD *srcPtr, intptr_t srcPitch,
  345.               intptr_t dstW, intptr_t dstH,
  346.                intptr_t srcW, intptr_t srcH) ;
  347.  
  348. void GDIDisplay::render()
  349. {
  350.   BITMAPINFO *bi = (BITMAPINFO *)info;
  351.   bi->bmiHeader.biWidth = theApp.filterWidth+1;
  352.   bi->bmiHeader.biHeight = -theApp.filterHeight;
  353.  
  354.   int pitch = theApp.filterWidth * 2 + 4;
  355.   if(systemColorDepth == 24)
  356.     pitch = theApp.filterWidth * 3;
  357.   else if(systemColorDepth == 32)
  358.     pitch = theApp.filterWidth * 4 + 4;
  359.  
  360.   if(theApp.filterFunction) {
  361.     bi->bmiHeader.biWidth = theApp.filterWidth * 2;
  362.     bi->bmiHeader.biHeight = -theApp.filterHeight * 2;
  363.    
  364.     if(systemColorDepth == 16)
  365.       (*theApp.filterFunction)(pix+pitch,
  366.                                pitch,
  367.                                (u8*)theApp.delta,
  368.                                (u8*)filterData,
  369.                                theApp.filterWidth*2*2,
  370.                                theApp.filterWidth,
  371.                                theApp.filterHeight);
  372.     else
  373.       (*theApp.filterFunction)(pix+pitch,
  374.                                pitch,
  375.                                (u8*)theApp.delta,
  376.                                (u8*)filterData,
  377.                                theApp.filterWidth*4*2,
  378.                                theApp.filterWidth,
  379.                                theApp.filterHeight);
  380.   }
  381.  
  382.   if(theApp.showSpeed && (theApp.videoOption > VIDEO_4X || theApp.skin != NULL)) {
  383.     char buffer[30];
  384.     if(theApp.showSpeed == 1)
  385.       sprintf(buffer, "%3d%%", systemSpeed);
  386.     else
  387.       sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
  388.               systemFrameSkip,
  389.               theApp.showRenderedFrames);
  390.  
  391.     if(theApp.filterFunction) {
  392.       int p = theApp.filterWidth * 4;
  393.       if(systemColorDepth == 24)
  394.         p = theApp.filterWidth * 6;
  395.       else if(systemColorDepth == 32)
  396.         p = theApp.filterWidth * 8;
  397.       if(theApp.showSpeedTransparent)
  398.         drawTextTransp((u8*)filterData,
  399.                        p,
  400.                        10,
  401.                        theApp.filterHeight*2-10,
  402.                        buffer);
  403.       else
  404.         drawText((u8*)filterData,
  405.                  p,
  406.                  10,
  407.                  theApp.filterHeight*2-10,
  408.                  buffer);      
  409.     } else {
  410.       if(theApp.showSpeedTransparent)
  411.         drawTextTransp((u8*)pix,
  412.                        pitch,
  413.                        10,
  414.                        theApp.filterHeight-10,
  415.                        buffer);
  416.       else
  417.         drawText((u8*)pix,
  418.                  pitch,
  419.                  10,
  420.                  theApp.filterHeight-10,
  421.                  buffer);
  422.     }
  423.   }
  424.  
  425.   POINT p;
  426.   p.x = theApp.dest.left;
  427.   p.y = theApp.dest.top;
  428.   CWnd *pWnd = theApp.m_pMainWnd;
  429.   pWnd->ScreenToClient(&p);
  430.   POINT p2;
  431.   p2.x = theApp.dest.right;
  432.   p2.y = theApp.dest.bottom;
  433.   pWnd->ScreenToClient(&p2);
  434.  
  435.   CDC *dc = pWnd->GetDC();
  436.  
  437.   /*  
  438.   StretchDIBits((HDC)*dc,
  439.                 p.x,
  440.                 p.y,
  441.                 p2.x - p.x,
  442.                 p2.y - p.y,
  443.                 0,
  444.                 0,
  445.                 theApp.rect.right,
  446.                 theApp.rect.bottom,
  447.                 theApp.filterFunction ? filterData : pix+pitch,
  448.                 bi,
  449.                 DIB_RGB_COLORS,
  450.                 SRCCOPY);
  451.  
  452.                 */
  453.  
  454.   HRESULT sig;
  455.   RECT rcClient;
  456.   D3DLOCKED_RECT lock_rect;
  457.        
  458.   IDirect3DSurface9 *surface_temp;
  459.   GetClientRect (*pWnd, & rcClient);
  460.   int w = abs (rcClient.left - rcClient.right);
  461.   int h = abs (rcClient.bottom - rcClient.top);
  462.   if (w <= 0 || h <= 0)
  463.     return ;
  464.        
  465.   sig = _Direct3D9_device->GetBackBuffer (0, 0, D3DBACKBUFFER_TYPE_MONO, & surface_temp);
  466.   assert (SUCCEEDED (sig));
  467.   sig = _Direct3D9_surface->LockRect (& _Direct3D9_LockRect, NULL, D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE);
  468.   assert (SUCCEEDED (sig));
  469.   // bilinear entryu .
  470.   bilinear (   (DWORD *)_Direct3D9_LockRect.pBits, _Direct3D9_LockRect.Pitch,
  471.  (DWORD *)theApp.filterFunction ? (DWORD *)filterData : (DWORD *) (pix+pitch),
  472.   theApp.filterFunction ? theApp.filterWidth*systemColorDepth/8*2 : pitch,
  473.     rcClient.right - rcClient.left,
  474.     rcClient.bottom - rcClient.top, theApp.rect.right, theApp.rect.bottom);
  475.   // malloc(4*4*256*(240+80));
  476.   sig = _Direct3D9_surface->UnlockRect ();
  477.   assert (SUCCEEDED (sig));
  478.  
  479.   sig = surface_temp->Release ();
  480.   assert (SUCCEEDED (sig));
  481.   _Direct3D9_device->UpdateSurface (_Direct3D9_surface, & rcClient, surface_temp, NULL);
  482.   _Direct3D9_device->Present (& rcClient, NULL, NULL, NULL);
  483.  
  484.   if(theApp.screenMessage) {
  485.     if(((GetTickCount() - theApp.screenMessageTime) < 3000) &&
  486.        !theApp.disableStatusMessage) {
  487.       dc->SetTextColor(RGB(255,0,0));
  488.       dc->SetBkMode(TRANSPARENT);
  489.       dc->TextOut(p.x+10, p2.y - 20, theApp.screenMessageBuffer);
  490.     } else {
  491.       theApp.screenMessage = false;
  492.     }
  493.   }
  494.  
  495.   pWnd->ReleaseDC(dc);
  496. }
  497.  
  498. void GDIDisplay::resetDevice (HWND window) {
  499.   if (_Direct3D9_root != nullptr)  {
  500.     if (_Direct3D9_device != nullptr)
  501.       _Direct3D9_device->Release ();
  502.     if (_Direct3D9_device != nullptr)
  503.       _Direct3D9_surface->Release ();
  504.     _Direct3D9_root->Release ();
  505.     _Direct3D9_device = nullptr;
  506.     _Direct3D9_surface = nullptr;
  507.     _Direct3D9_root = nullptr;
  508.   }
  509.  
  510.   _Direct3D9_root = Direct3DCreate9 (DIRECT3D_VERSION_);
  511.   assert (_Direct3D9_root != nullptr);
  512.  
  513.   D3DPRESENT_PARAMETERS d3dpp;
  514.   ZeroMemory (& d3dpp, sizeof (d3dpp));
  515.  
  516.   _scr_x = GetSystemMetrics (SM_CXSCREEN);
  517.   _scr_y = GetSystemMetrics (SM_CYSCREEN);
  518.  
  519.   d3dpp.BackBufferFormat      = D3DFMT_X8R8G8B8;
  520.   d3dpp.SwapEffect            = D3DSWAPEFFECT_DISCARD;
  521.   d3dpp.Flags                 = 0;
  522.   d3dpp.hDeviceWindow         = window;
  523.   d3dpp.Windowed              = TRUE;
  524.   d3dpp.BackBufferWidth       = _scr_x;
  525.   d3dpp.BackBufferHeight      = _scr_y;
  526.   d3dpp.PresentationInterval  = D3DPRESENT_INTERVAL_IMMEDIATE; /* Disable VSync */
  527.  
  528.   HRESULT sig = _Direct3D9_root->CreateDevice (0,
  529.                         D3DDEVTYPE_HAL,
  530.                             window,
  531.                               D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, & _Direct3D9_device);
  532.   assert (SUCCEEDED (sig));
  533.  
  534.   sig = _Direct3D9_device->CreateOffscreenPlainSurface (_scr_x,
  535.         _scr_y, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM,
  536.       & _Direct3D9_surface, NULL);
  537.   assert (SUCCEEDED (sig));
  538. }
  539.  
  540. int GDIDisplay::selectFullScreenMode(GUID **)
  541. {
  542.   HWND wnd = GetDesktopWindow();
  543.   RECT r;
  544.   GetWindowRect(wnd, &r);
  545.   int w = (r.right - r.left) & 4095;
  546.   int h = (r.bottom - r.top) & 4095;
  547.   HDC dc = GetDC(wnd);
  548.   int c = GetDeviceCaps(dc, BITSPIXEL);
  549.   ReleaseDC(wnd, dc);
  550.  
  551.   return (c << 24) | (w << 12) | h;
  552. }
  553.  
  554. IDisplay *newGDIDisplay()
  555. {
  556.   return new GDIDisplay();
  557. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement