Mercurial > vba-linux
view src/win32/Direct3D.cpp @ 2:3549bbe597ed
adding makefile.am
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 10:31:47 -0600 |
parents | f9f4f1b99eed |
children |
line wrap: on
line source
1 #include "stdafx.h"3 #define DIRECT3D_VERSION 0x08004 #include "d3d8.h"5 #include "d3dx8.h"7 #include "resource.h"8 #include "MainWnd.h"9 #include "Reg.h"10 #include "VBA.h"12 //#include "../common/System.h"13 #include "../gba/GBAGlobals.h"14 #include "../gb/gbGlobals.h"15 #include "../common/Text.h"16 #include "../version.h"18 #ifdef MMX19 extern "C" bool cpu_mmx;21 extern bool detectMMX();22 #endif24 extern int Init_2xSaI(u32);25 extern void directXMessage(const char *);26 extern void winlog(const char *, ...);28 typedef struct _D3DTLVERTEX29 {30 float sx; /* Screen coordinates */31 float sy;32 float sz;33 float rhw; /* Reciprocal of homogeneous w */34 D3DCOLOR color; /* Vertex color */35 float tu; /* Texture coordinates */36 float tv;37 _D3DTLVERTEX() { }38 _D3DTLVERTEX(const D3DVECTOR& v, float _rhw,39 D3DCOLOR _color,40 float _tu, float _tv)41 {42 sx = v.x; sy = v.y; sz = v.z; rhw = _rhw;43 color = _color;44 tu = _tu; tv = _tv;45 }46 } D3DTLVERTEX, *LPD3DTLVERTEX;48 #define D3DFVF_TLVERTEX D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX150 class Direct3DDisplay : public IDisplay51 {52 public:53 Direct3DDisplay();54 virtual ~Direct3DDisplay();56 virtual bool initialize();57 virtual void cleanup();58 virtual void render();59 virtual void checkFullScreen();60 virtual void renderMenu();61 virtual void clear();62 virtual bool changeRenderSize(int w, int h);63 virtual void resize(int w, int h);64 virtual DISPLAY_TYPE getType() { return DIRECT_3D; };65 virtual void setOption(const char *, int);66 virtual int selectFullScreenMode(GUID * *);68 private:69 HINSTANCE d3dDLL;70 LPDIRECT3D8 pD3D;71 LPDIRECT3DDEVICE8 pDevice;72 LPDIRECT3DTEXTURE8 pTexture;73 D3DSURFACE_DESC dsdBackBuffer;74 D3DPRESENT_PARAMETERS dpp;75 D3DFORMAT screenFormat;76 int width;77 int height;78 bool filterDisabled;79 ID3DXFont *pFont;80 bool failed;81 unsigned int textureSize;82 D3DTLVERTEX verts[4];85 void restoreDeviceObjects();86 void invalidateDeviceObjects();87 bool initializeOffscreen(int w, int h);88 void updateFiltering(int);89 void calculateVertices();90 };92 Direct3DDisplay::Direct3DDisplay()93 {94 d3dDLL = NULL;95 pD3D = NULL;96 pDevice = NULL;97 pTexture = NULL;98 pFont = NULL;99 screenFormat = D3DFMT_R5G6B5;100 width = 0;101 height = 0;102 filterDisabled = false;103 failed = false;104 textureSize = 0;105 }107 Direct3DDisplay::~Direct3DDisplay()108 {109 cleanup();110 }112 void Direct3DDisplay::cleanup()113 {114 if (pD3D != NULL)115 {116 if (pFont)117 {118 pFont->Release();119 pFont = NULL;120 }122 if (pTexture)123 {124 pTexture->Release();125 pTexture = NULL;126 }128 if (pDevice)129 {130 pDevice->Release();131 pDevice = NULL;132 }134 pD3D->Release();135 pD3D = NULL;137 if (d3dDLL != NULL)138 {139 FreeLibrary(d3dDLL);140 d3dDLL = NULL;141 }142 }143 }145 bool Direct3DDisplay::initialize()146 {147 CWnd *pWnd = theApp.m_pMainWnd;149 d3dDLL = LoadLibrary("D3D8.DLL");150 LPDIRECT3D8 (WINAPI *D3DCreate)(UINT);151 if (d3dDLL != NULL)152 {153 D3DCreate = (LPDIRECT3D8 (WINAPI *)(UINT))154 GetProcAddress(d3dDLL, "Direct3DCreate8");156 if (D3DCreate == NULL)157 {158 directXMessage("Direct3DCreate8");159 return FALSE;160 }161 }162 else163 {164 directXMessage("D3D8.DLL");165 return FALSE;166 }168 pD3D = D3DCreate(120);170 if (pD3D == NULL)171 {172 winlog("Error creating Direct3D object\n");173 return FALSE;174 }176 theApp.mode320Available = false;177 theApp.mode640Available = false;178 theApp.mode800Available = false;180 D3DDISPLAYMODE mode;181 pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode);183 switch (mode.Format)184 {185 case D3DFMT_R8G8B8:186 systemColorDepth = 24;187 systemRedShift = 19;188 systemGreenShift = 11;189 systemBlueShift = 3;190 break;191 case D3DFMT_X8R8G8B8:192 systemColorDepth = 32;193 systemRedShift = 19;194 systemGreenShift = 11;195 systemBlueShift = 3;196 Init_2xSaI(32);197 break;198 case D3DFMT_R5G6B5:199 systemColorDepth = 16;200 systemRedShift = 11;201 systemGreenShift = 6;202 systemBlueShift = 0;203 Init_2xSaI(565);204 break;205 case D3DFMT_X1R5G5B5:206 systemColorDepth = 16;207 systemRedShift = 10;208 systemGreenShift = 5;209 systemBlueShift = 0;210 Init_2xSaI(555);211 break;212 default:213 systemMessage(0, "Unsupport D3D format %d", mode.Format);214 return false;215 }216 theApp.fsColorDepth = systemColorDepth;218 #ifdef MMX219 if (!theApp.disableMMX)220 cpu_mmx = theApp.detectMMX();221 else222 cpu_mmx = 0;223 #endif225 screenFormat = mode.Format;227 // check for available fullscreen modes228 ZeroMemory(&dpp, sizeof(dpp));229 dpp.Windowed = TRUE;230 dpp.BackBufferFormat = mode.Format;231 dpp.BackBufferCount = 1;232 dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;233 dpp.BackBufferWidth = theApp.surfaceSizeX;234 dpp.BackBufferHeight = theApp.surfaceSizeY;236 HRESULT hret = pD3D->CreateDevice(D3DADAPTER_DEFAULT,237 D3DDEVTYPE_HAL,238 pWnd->GetSafeHwnd(),239 D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,240 &dpp,241 &pDevice);242 if (!SUCCEEDED(hret))243 {244 winlog("Error creating Direct3DDevice %08x\n", hret);245 return false;246 }248 restoreDeviceObjects();250 switch (systemColorDepth)251 {252 case 16:253 {254 for (int i = 0; i < 0x10000; i++)255 {256 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |257 (((i & 0x3e0) >> 5) << systemGreenShift) |258 (((i & 0x7c00) >> 10) << systemBlueShift);259 }260 break;261 }262 case 24:263 case 32:264 {265 for (int i = 0; i < 0x10000; i++)266 {267 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |268 (((i & 0x3e0) >> 5) << systemGreenShift) |269 (((i & 0x7c00) >> 10) << systemBlueShift);270 }271 break;272 }273 }275 theApp.updateFilter();276 theApp.updateIFB();278 if (failed)279 return false;281 pWnd->DragAcceptFiles(TRUE);283 return TRUE;284 }286 bool Direct3DDisplay::initializeOffscreen(int w, int h)287 {288 int size = 256;289 if (w > 512 || h > 512)290 size = 1024;291 else if (w > 256 || h > 256)292 size = 512;293 textureSize = size;295 UINT ww = size;296 UINT hh = size;297 D3DFORMAT format = screenFormat;299 if (SUCCEEDED(D3DXCheckTextureRequirements(pDevice,300 &ww,301 &hh,302 NULL,303 0,304 &format,305 D3DPOOL_MANAGED)))306 {307 if ((int)ww < w || (int)hh < h)308 {309 if (theApp.filterFunction)310 {311 filterDisabled = true;312 theApp.filterFunction = NULL;313 systemMessage(0, "3D card cannot support needed texture size for filter function. Disabling it");314 }315 }316 else317 filterDisabled = false;318 if (SUCCEEDED(D3DXCreateTexture(pDevice,319 ww,320 hh,321 0,322 0,323 format,324 D3DPOOL_MANAGED,325 &pTexture)))326 {327 width = w;328 height = h;329 return true;330 }331 }332 return false;333 }335 void Direct3DDisplay::updateFiltering(int filter)336 {337 switch (filter)338 {339 default:340 case 0:341 // point filtering342 pDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_POINT);343 pDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_POINT);344 pDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);345 break;346 case 1:347 // bilinear348 pDevice->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);349 pDevice->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);350 pDevice->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_POINT);351 break;352 }353 }355 void Direct3DDisplay::restoreDeviceObjects()356 {357 // Store render target surface desc358 LPDIRECT3DSURFACE8 pBackBuffer;359 HRESULT hr;360 if (SUCCEEDED(hr = pDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer)))361 {362 pBackBuffer->GetDesc(&dsdBackBuffer);363 pBackBuffer->Release();364 }365 else366 systemMessage(0, "Failed GetBackBuffer %08x", hr);368 // Set up the texture369 pDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);370 pDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);371 pDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);373 int filter = regQueryDwordValue("d3dFilter", 0);374 if (filter < 0 || filter > 3)375 filter = 0;376 updateFiltering(filter);378 // Set miscellaneous render states379 pDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE);380 pDevice->SetRenderState(D3DRS_ZENABLE, FALSE);382 // Set the projection matrix383 D3DXMATRIX matProj;384 FLOAT fAspect = ((FLOAT)dsdBackBuffer.Width) / dsdBackBuffer.Height;385 D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, fAspect, 1.0f, 100.0f);386 pDevice->SetTransform(D3DTS_PROJECTION, &matProj);388 // turn off lighting389 pDevice->SetRenderState(D3DRS_LIGHTING, FALSE);391 if (pFont)392 {393 pFont->Release();394 pFont = NULL;395 }396 // Create a D3D font using D3DX397 HFONT hFont = CreateFont(14, 0, 0, 0, FW_BOLD, FALSE, FALSE, FALSE,398 ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,399 ANTIALIASED_QUALITY, FF_DONTCARE, "Arial");400 D3DXCreateFont(pDevice, hFont, &pFont);401 }403 void Direct3DDisplay::clear()404 {}406 void Direct3DDisplay::renderMenu()407 {408 checkFullScreen();409 if (theApp.m_pMainWnd)410 theApp.m_pMainWnd->DrawMenuBar();411 }413 void Direct3DDisplay::checkFullScreen()414 {415 // if(tripleBuffering)416 // pDirect3D->FlipToGDISurface();417 }419 void Direct3DDisplay::calculateVertices()420 {421 // color422 D3DCOLOR col = 0xFFFFFFFF;424 // calculate rhw425 FLOAT z = 1.0f;426 FLOAT rhw = 1.0f / (z * 990.0f + 10.0f);428 // -0.5f is necessary in order to match texture alignment to display pixels429 FLOAT left = -0.5f;430 FLOAT right = dpp.BackBufferWidth - 0.5f;431 FLOAT top = -0.5f;432 FLOAT bottom = dpp.BackBufferHeight - 0.5f;434 FLOAT textureX = (FLOAT)theApp.rect.right / (FLOAT)textureSize;435 FLOAT textureY = (FLOAT)theApp.rect.bottom / (FLOAT)textureSize;437 //#define D3D_DRAW_SINGLE_RECTANGLE438 #ifdef D3D_DRAW_SINGLE_RECTANGLE439 // set up a rectangle440 verts[0] = D3DTLVERTEX(D3DXVECTOR3(left, top, z), rhw, col, 0.0f, 0.0f);441 verts[1] = D3DTLVERTEX(D3DXVECTOR3(right, top, z), rhw, col, textureX, 0.0f);442 verts[2] = D3DTLVERTEX(D3DXVECTOR3(right, bottom, z), rhw, col, textureX, textureY);443 verts[3] = D3DTLVERTEX(D3DXVECTOR3(left, bottom, z), rhw, col, 0.0f, textureY);444 #else445 // set up triangles446 verts[0] = D3DTLVERTEX(D3DXVECTOR3(left, bottom, z), rhw, col, 0.0f, textureY);447 verts[1] = D3DTLVERTEX(D3DXVECTOR3(left, top, z), rhw, col, 0.0f, 0.0f);448 verts[2] = D3DTLVERTEX(D3DXVECTOR3(right, bottom, z), rhw, col, textureX, textureY);449 verts[3] = D3DTLVERTEX(D3DXVECTOR3(right, top, z), rhw, col, textureX, 0.0f);450 #endif451 }453 void Direct3DDisplay::render()454 {455 if (!pDevice)456 return;458 // Test the cooperative level to see if it's okay to render459 if (FAILED(pDevice->TestCooperativeLevel()))460 {461 return;462 }463 pDevice->Clear(0L, NULL, D3DCLEAR_TARGET, 0x000000ff, 1.0f, 0L);465 if (SUCCEEDED(pDevice->BeginScene()))466 {467 D3DLOCKED_RECT locked;468 if (pTexture && SUCCEEDED(pTexture->LockRect(0, &locked, NULL, 0)))469 {470 if (theApp.filterFunction)471 {472 if (systemColorDepth == 16)473 theApp.filterFunction(pix + theApp.filterWidth * 2 + 4,474 theApp.filterWidth*2 + 4,475 (u8 *)theApp.delta,476 (u8 *)locked.pBits,477 locked.Pitch,478 theApp.filterWidth,479 theApp.filterHeight);480 else481 theApp.filterFunction(pix + theApp.filterWidth * 4 + 4,482 theApp.filterWidth * 4 + 4,483 (u8 *)theApp.delta,484 (u8 *)locked.pBits,485 locked.Pitch,486 theApp.filterWidth,487 theApp.filterHeight);488 }489 else490 {491 int copyX = 240;492 int copyY = 160;494 if (systemCartridgeType == 1)495 {496 if (gbBorderOn)497 {498 copyX = 256;499 copyY = 224;500 }501 else502 {503 copyX = 160;504 copyY = 144;505 }506 }507 // MMX doesn't seem to be faster to copy the data508 __asm {509 mov eax, copyX;510 mov ebx, copyY;512 mov esi, pix;513 mov edi, locked.pBits;514 mov edx, locked.Pitch;515 cmp systemColorDepth, 16;516 jnz gbaOtherColor;517 sub edx, eax;518 sub edx, eax;519 lea esi, [esi+2*eax+4];520 shr eax, 1;521 gbaLoop16bit:522 mov ecx, eax;523 repz movsd;524 inc esi;525 inc esi;526 inc esi;527 inc esi;528 add edi, edx;529 dec ebx;530 jnz gbaLoop16bit;531 jmp gbaLoopEnd;532 gbaOtherColor:533 cmp systemColorDepth, 32;534 jnz gbaOtherColor2;536 sub edx, eax;537 sub edx, eax;538 sub edx, eax;539 sub edx, eax;540 lea esi, [esi+4*eax+4];541 gbaLoop32bit:542 mov ecx, eax;543 repz movsd;544 add esi, 4;545 add edi, edx;546 dec ebx;547 jnz gbaLoop32bit;548 jmp gbaLoopEnd;549 gbaOtherColor2:550 lea eax, [eax+2*eax];551 sub edx, eax;552 gbaLoop24bit:553 mov ecx, eax;554 shr ecx, 2;555 repz movsd;556 add edi, edx;557 dec ebx;558 jnz gbaLoop24bit;559 gbaLoopEnd:560 }561 }563 if (theApp.videoOption > VIDEO_4X && theApp.showSpeed)564 {565 char buffer[30];566 if (theApp.showSpeed == 1)567 sprintf(buffer, "%3d%%", systemSpeed);568 else569 sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,570 systemFrameSkip,571 theApp.showRenderedFrames);572 if (theApp.showSpeedTransparent)573 drawTextTransp((u8 *)locked.pBits,574 locked.Pitch,575 theApp.rect.left+10,576 theApp.rect.bottom-10,577 buffer);578 else579 drawText((u8 *)locked.pBits,580 locked.Pitch,581 theApp.rect.left+10,582 theApp.rect.bottom-10,583 buffer);584 }586 if (textMethod == 1)587 {588 DrawTextMessages((u8 *)locked.pBits, locked.Pitch, theApp.rect.left, theApp.rect.bottom);589 }591 pTexture->UnlockRect(0);593 // set the texture594 pDevice->SetTexture(0, pTexture);596 // configure shader for vertex type597 pDevice->SetVertexShader(D3DFVF_TLVERTEX);599 #ifdef D3D_DRAW_SINGLE_RECTANGLE600 // draw the rectangle601 pDevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, sizeof(D3DTLVERTEX));602 //#undef D3D_DRAW_RECT603 #else604 // draw the triangles605 pDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, verts, sizeof(D3DTLVERTEX));606 #endif607 }609 if (textMethod == 2)610 {611 for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++)612 {613 if (theApp.screenMessage[slot])614 {615 if ((theApp.screenMessageDuration[slot] < 0 ||616 (int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) &&617 (!theApp.disableStatusMessage || slot == 1 || slot == 2) && pFont)618 {619 pFont->Begin();620 RECT r;621 D3DCOLOR color;623 r.left = 10;624 r.top = dpp.BackBufferHeight - 20*(slot+1);625 r.right = dpp.BackBufferWidth - 10;626 r.bottom = r.top + 20;628 if (outlinedText)629 {630 color = textColor != 7 ? D3DCOLOR_ARGB(255, 0, 0, 0) : D3DCOLOR_ARGB(255, 255, 255, 255);632 // draw outline633 const static int xd [8] = {-1, 0, 1, 1, 1, 0, -1, -1};634 const static int yd [8] = {-1, -1, -1, 0, 1, 1, 1, 0};635 for (int i = 0; i < 8; i++)636 {637 RECT r2 = r;638 r2.left += xd[i]; r2.right += xd[i];639 r2.top += yd[i]; r2.bottom += yd[i];641 pFont->DrawText(theApp.screenMessageBuffer[slot], -1, &r2, 0, color);642 }643 }645 // draw center text646 switch (textColor)647 {648 case 0:649 color = D3DCOLOR_ARGB(255, 255, 255, 255); break;650 case 1:651 color = D3DCOLOR_ARGB(255, 255, 0, 0); break;652 case 2:653 color = D3DCOLOR_ARGB(255, 255, 255, 0); break;654 case 3:655 color = D3DCOLOR_ARGB(255, 0, 255, 0); break;656 case 4:657 color = D3DCOLOR_ARGB(255, 0, 255, 255); break;658 case 5:659 color = D3DCOLOR_ARGB(255, 0, 0, 255); break;660 case 6:661 color = D3DCOLOR_ARGB(255, 255, 0, 255); break;662 case 7:663 color = D3DCOLOR_ARGB(255, 0, 0, 0); break;664 }665 pFont->DrawText(theApp.screenMessageBuffer[slot], -1, &r, 0, color);667 pFont->End();668 }669 else670 {671 theApp.screenMessage[slot] = false;672 }673 }674 }675 }677 pDevice->EndScene();679 pDevice->Present(NULL, NULL, NULL, NULL);680 }681 }683 void Direct3DDisplay::invalidateDeviceObjects()684 {685 if (pFont)686 pFont->Release();687 pFont = NULL;688 }690 void Direct3DDisplay::resize(int w, int h)691 {692 if (pDevice && w > 0 && h > 0)693 {694 dpp.BackBufferWidth = w;695 dpp.BackBufferHeight = h;696 HRESULT hr;697 invalidateDeviceObjects();698 if (SUCCEEDED(hr = pDevice->Reset(&dpp)))699 {700 restoreDeviceObjects();701 }702 else703 systemMessage(0, "Failed device reset %08x", hr);704 }705 calculateVertices();706 }708 bool Direct3DDisplay::changeRenderSize(int w, int h)709 {710 if (w != width || h != height)711 {712 if (pTexture)713 {714 pTexture->Release();715 pTexture = NULL;716 }717 if (!initializeOffscreen(w, h))718 {719 failed = true;720 return false;721 }722 }723 calculateVertices();725 return true;726 }728 void Direct3DDisplay::setOption(const char *option, int value)729 {730 if (!strcmp(option, "d3dFilter"))731 updateFiltering(value);732 }734 int Direct3DDisplay::selectFullScreenMode(GUID * *)735 {736 HWND wnd = GetDesktopWindow();737 RECT r;738 GetWindowRect(wnd, &r);739 int w = (r.right - r.left) & 4095;740 int h = (r.bottom - r.top) & 4095;741 HDC dc = GetDC(wnd);742 int c = GetDeviceCaps(dc, BITSPIXEL);743 ReleaseDC(wnd, dc);745 return (c << 24) | (w << 12) | h;746 }748 IDisplay *newDirect3DDisplay()749 {750 return new Direct3DDisplay();751 }