annotate src/win32/Direct3D.cpp @ 1:f9f4f1b99eed

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