Platform_Win32_Screen_D3D9.cpp
Go to the documentation of this file.00001 //*** Platform_Win32_Screen_D3D9.cpp *** 00002 00003 #include "Platform_Win32_Screen_D3D9.h" 00004 00005 #define WIN32_LEAN_AND_MEAN 00006 #define VC_EXTRALEAN 00007 #include <d3d9.h> 00008 00009 #include "Platform_OS.h" 00010 #define DebugPrint(x) Platform::GetPlatform_OS()->OutputDebugText x; 00011 00012 //*** Constructor *** 00013 00014 Platform_Win32_Screen_D3D9::Platform_Win32_Screen_D3D9(struct HWND__* windowHandle, bool fullscreen, int screenWidth, int screenHeight, bool interpolationMode): 00015 windowHandle_(windowHandle), 00016 interpolationMode_(interpolationMode), 00017 fullscreen_(fullscreen), 00018 screenWidth_(screenWidth), 00019 screenHeight_(screenHeight), 00020 d3dDLL_(0), 00021 direct3D_(0), 00022 device_(0), 00023 backbuffer1_(0), 00024 backbuffer2_(0), 00025 backbufferWidth_(0), 00026 backbufferHeight_(0), 00027 usingDynamicTexture_(false), 00028 buffer1Filled_(false), 00029 buffer2Filled_(false), 00030 lastPresentWidth_(0), 00031 lastPresentHeight_(0) 00032 { 00033 DebugPrint(("Creating Platform_Win32_Screen_D3D9...\n\tfullscreen:%d\n\tscreenWidth:%d\n\tscreenHeight:%d\n\tinterpolationMode:%d\n",fullscreen,screenWidth,screenHeight,interpolationMode)); 00034 } 00035 00036 00037 //*** Setup *** 00038 00039 bool Platform_Win32_Screen_D3D9::Setup() 00040 { 00041 00042 // Create D3D object 00043 d3dDLL_=LoadLibrary("d3d9.dll"); 00044 if (!d3dDLL_) 00045 { 00046 DebugPrint(("Couldn't find d3d9.dll\n")); 00047 return false; 00048 } 00049 00050 // Create DirectDraw object 00051 typedef IDirect3D9 * (WINAPI *Direct3DCreate9Definition)( unsigned int SDKVersion ); 00052 Direct3DCreate9Definition Direct3DCreate9=(Direct3DCreate9Definition)GetProcAddress((HMODULE)d3dDLL_, "Direct3DCreate9"); 00053 if (Direct3DCreate9==0) 00054 { 00055 DebugPrint(("Failed to find function entry point in d3d9.dll\n")); 00056 return false; 00057 } 00058 00059 direct3D_=Direct3DCreate9(D3D_SDK_VERSION); 00060 if (!direct3D_) 00061 { 00062 DebugPrint(("Couldn't create Direct3D object\n")); 00063 return false; 00064 } 00065 00066 00067 // Get present parameters 00068 D3DPRESENT_PARAMETERS d3dpp; 00069 if (fullscreen_) 00070 { 00071 SetWindowPos(windowHandle_,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); 00072 SetWindowLong(windowHandle_,GWL_STYLE,WS_POPUPWINDOW|WS_VISIBLE); 00073 ZeroMemory( &d3dpp, sizeof(d3dpp) ); 00074 00075 d3dpp.BackBufferWidth=screenWidth_; 00076 d3dpp.BackBufferHeight=screenHeight_; 00077 d3dpp.BackBufferFormat=D3DFMT_R5G6B5; 00078 d3dpp.BackBufferCount=2; 00079 d3dpp.MultiSampleType=D3DMULTISAMPLE_NONE; 00080 d3dpp.MultiSampleQuality=0; 00081 d3dpp.SwapEffect=D3DSWAPEFFECT_FLIP; 00082 d3dpp.hDeviceWindow=windowHandle_; 00083 d3dpp.Windowed=0; 00084 d3dpp.EnableAutoDepthStencil=FALSE; 00085 d3dpp.AutoDepthStencilFormat=D3DFMT_D24S8; 00086 d3dpp.Flags=0; 00087 d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT; 00088 d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_ONE; 00089 } 00090 else 00091 { 00092 ZeroMemory( &d3dpp, sizeof(d3dpp) ); 00093 d3dpp.Windowed = TRUE; 00094 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 00095 d3dpp.BackBufferFormat=D3DFMT_UNKNOWN; 00096 d3dpp.EnableAutoDepthStencil = FALSE; 00097 d3dpp.BackBufferCount=1; 00098 d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8; 00099 d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; 00100 d3dpp.FullScreen_RefreshRateInHz=D3DPRESENT_RATE_DEFAULT; 00101 d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_ONE; 00102 } 00103 00104 // Set device adapter to use 00105 UINT AdapterToUse=D3DADAPTER_DEFAULT; 00106 D3DDEVTYPE DeviceType=D3DDEVTYPE_HAL; 00107 00108 // Create the D3DDevice 00109 HRESULT ret=direct3D_->CreateDevice(AdapterToUse,DeviceType,windowHandle_, D3DCREATE_SOFTWARE_VERTEXPROCESSING,&d3dpp,&device_); 00110 if (FAILED(ret) || !device_) 00111 { 00112 DebugPrint(("Couldn't create Direct3D Device\n")); 00113 return false; 00114 } 00115 00116 00117 // Use the right type of filtering for the requested interpolation mode 00118 device_->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_NONE ); 00119 if (interpolationMode_) 00120 { 00121 device_->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR ); 00122 device_->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR ); 00123 } 00124 else 00125 { 00126 device_->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_POINT); 00127 device_->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_POINT); 00128 } 00129 00130 device_->SetSamplerState(0,D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); 00131 device_->SetSamplerState(0,D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); 00132 00133 DebugPrint(("...Platform_Win32_Screen_D3D9 created\n")); 00134 return true; 00135 } 00136 00137 00138 //*** Destructor *** 00139 00140 Platform_Win32_Screen_D3D9::~Platform_Win32_Screen_D3D9() 00141 { 00142 DebugPrint(("Destroying Platform_Win32_Screen_D3D9...\n")); 00143 00144 if (backbuffer1_) 00145 { 00146 backbuffer1_->Release(); 00147 } 00148 00149 if (backbuffer2_) 00150 { 00151 backbuffer2_->Release(); 00152 } 00153 00154 if (device_) 00155 { 00156 device_->Release(); 00157 } 00158 00159 if (direct3D_) 00160 { 00161 direct3D_->Release(); 00162 } 00163 00164 if (d3dDLL_) 00165 { 00166 FreeLibrary((HMODULE)d3dDLL_); 00167 } 00168 00169 if (fullscreen_) 00170 { 00171 SetWindowLong(windowHandle_,GWL_STYLE,WS_OVERLAPPEDWINDOW | WS_VISIBLE ); 00172 } 00173 00174 SetWindowPos(windowHandle_,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE | SWP_NOMOVE | SWP_NOREDRAW | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); 00175 00176 00177 DebugPrint(("... Platform_Win32_Screen_D3D9 destroyed\n")); 00178 } 00179 00180 00181 //*** Present *** 00182 00183 bool Platform_Win32_Screen_D3D9::Present(unsigned short* bitmapData, int bitmapWidth, int bitmapHeight, unsigned short modulate, unsigned short backgroundColor) 00184 { 00185 lastPresentWidth_=bitmapWidth; 00186 lastPresentHeight_=bitmapHeight; 00187 unsigned int color=RGB16TO32(backgroundColor); 00188 00189 00190 HRESULT result=S_OK; 00191 00192 result=device_->Clear( 0, 0, D3DCLEAR_TARGET, color, 0, 0); 00193 if (FAILED(result)) 00194 { 00195 DebugPrint(("Clear failed\n")); 00196 return false; 00197 } 00198 00199 result=device_->BeginScene(); 00200 if (FAILED(result)) 00201 { 00202 DebugPrint(("BeginScene failed\n")); 00203 return false; 00204 } 00205 00206 00207 if (!CopyBitmapToBackBuffer(bitmapData,bitmapWidth,bitmapHeight,backgroundColor)) 00208 { 00209 DebugPrint(("CopyBitmapToBackBuffer failed\n")); 00210 return false; 00211 } 00212 00213 if (buffer2Filled_) 00214 { 00215 if (!CopyBackBufferToFrontBuffer(bitmapWidth, bitmapHeight, modulate)) 00216 { 00217 DebugPrint(("CopyBackBufferToFrontBuffer failed\n")); 00218 return false; 00219 } 00220 } 00221 00222 result=device_->EndScene(); 00223 if (FAILED(result)) 00224 { 00225 DebugPrint(("EndScene failed\n")); 00226 return false; 00227 } 00228 00229 result=device_->Present(0, 0, 0, 0 ); 00230 if (FAILED(result)) 00231 { 00232 DebugPrint(("Present failed\n")); 00233 return false; 00234 } 00235 00236 // Swap buffers 00237 IDirect3DTexture9* temp=backbuffer2_; 00238 backbuffer2_=backbuffer1_; 00239 backbuffer1_=temp; 00240 if (!buffer1Filled_) 00241 { 00242 buffer1Filled_=true; 00243 } 00244 else if (!buffer2Filled_) 00245 { 00246 buffer2Filled_=true; 00247 } 00248 00249 00250 return true; 00251 } 00252 00253 00254 //*** CopyBitmapToBackBuffer *** 00255 00256 bool Platform_Win32_Screen_D3D9::CopyBitmapToBackBuffer(unsigned short* bitmapData, int bitmapWidth, int bitmapHeight, unsigned short backgroundColor) 00257 { 00258 if (!backbuffer1_ || backbufferWidth_<bitmapWidth || backbufferHeight_<bitmapHeight) 00259 { 00260 if (!CreateBackBuffers(bitmapWidth,bitmapHeight)) 00261 { 00262 DebugPrint(("Couldn't create backbuffers\n")); 00263 return false; 00264 } 00265 } 00266 00267 D3DLOCKED_RECT lockedRect; 00268 HRESULT result=S_OK; 00269 if (usingDynamicTexture_) 00270 { 00271 result=backbuffer1_->LockRect(0,&lockedRect,0,D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE ); 00272 } 00273 else 00274 { 00275 RECT rect; 00276 rect.top=0; 00277 rect.left=0; 00278 rect.right=bitmapWidth; 00279 rect.bottom=bitmapHeight; 00280 result=backbuffer1_->LockRect(0,&lockedRect,&rect,D3DLOCK_DISCARD | D3DLOCK_NOOVERWRITE ); 00281 } 00282 00283 if (FAILED(result)) 00284 { 00285 DebugPrint(("Failed to lock backbuffer\n")); 00286 return false; 00287 } 00288 00289 unsigned char* destination=static_cast<unsigned char*>(lockedRect.pBits); 00290 int pitch=lockedRect.Pitch; 00291 unsigned char* source=reinterpret_cast<unsigned char*>(bitmapData); 00292 int bitmapPitch=bitmapWidth*2; 00293 int dwords=bitmapWidth/2; 00294 00295 00296 if (pitch==bitmapPitch) 00297 { 00298 memcpy(destination,source,pitch*bitmapHeight); 00299 } 00300 else 00301 { 00302 if (interpolationMode_) 00303 { 00304 for (int y=0; y<bitmapHeight; y++) 00305 { 00306 memcpy(destination,source,bitmapPitch); 00307 destination[bitmapPitch]=(unsigned char)(backgroundColor & 0xff); 00308 destination[bitmapPitch+1]=(unsigned char)(backgroundColor >> 8); 00309 destination+=pitch; 00310 source+=bitmapPitch; 00311 } 00312 } 00313 else 00314 { 00315 for (int y=0; y<bitmapHeight; y++) 00316 { 00317 memcpy(destination,source,bitmapPitch); 00318 destination+=pitch; 00319 source+=bitmapPitch; 00320 } 00321 } 00322 } 00323 00324 /* if (interpolationMode_) 00325 { 00326 unsigned short* dest=static_cast<unsigned short*>(destination); 00327 int width=bitmap->GetWidth(); 00328 for (int x=0; x<width; x++) 00329 { 00330 *dest=backgroundColor; 00331 dest++; 00332 } 00333 dest+=pitch; 00334 for (int x=0; x<width; x++) 00335 { 00336 *dest=backgroundColor; 00337 dest++; 00338 } 00339 } 00340 */ 00341 00342 00343 result=backbuffer1_->UnlockRect(0); 00344 if (FAILED(result)) 00345 { 00346 DebugPrint(("Failed to unlock backbuffer\n")); 00347 return false; 00348 } 00349 00350 return true; 00351 } 00352 00353 00354 //*** CopyBackBufferToFrontBuffer *** 00355 00356 bool Platform_Win32_Screen_D3D9::CopyBackBufferToFrontBuffer(int bitmapWidth, int bitmapHeight, unsigned short modulate) 00357 { 00358 struct Vertex 00359 { 00360 float x; 00361 float y; 00362 float z; 00363 float rhw; 00364 unsigned int color; 00365 float u; 00366 float v; 00367 }; 00368 00369 Vertex quad[4]; 00370 00371 float x1=0; 00372 float y1=0; 00373 float x2=0; 00374 float y2=0; 00375 00376 unsigned int color=RGB16TO32(modulate); 00377 if (interpolationMode_) 00378 { 00379 float hscale=screenWidth_/(float)bitmapWidth; 00380 float vscale=screenHeight_/(float)bitmapHeight; 00381 float pixelScale=min(hscale,vscale); 00382 00383 float hborder=(screenWidth_-pixelScale*bitmapWidth)/2; 00384 float vborder=(screenHeight_-pixelScale*bitmapHeight)/2; 00385 x1=hborder; 00386 y1=vborder; 00387 x2=x1+pixelScale*bitmapWidth; 00388 y2=y1+pixelScale*bitmapHeight; 00389 } 00390 else 00391 { 00392 int hscale=screenWidth_/bitmapWidth; 00393 int vscale=screenHeight_/bitmapHeight; 00394 int pixelScale=min(hscale,vscale); 00395 00396 int hborder=(screenWidth_-pixelScale*bitmapWidth)/2; 00397 int vborder=(screenHeight_-pixelScale*bitmapHeight)/2; 00398 x1=(float)hborder; 00399 y1=(float)vborder; 00400 x2=x1+(float)(pixelScale*bitmapWidth); 00401 y2=y1+(float)(pixelScale*bitmapHeight); 00402 } 00403 00404 00405 quad[0].x=x2-0.5f; 00406 quad[0].y=y2-0.5f; 00407 quad[0].z=0; 00408 quad[0].rhw=0.5f; 00409 quad[0].color=color; 00410 quad[0].u=bitmapWidth/(float)backbufferWidth_; 00411 quad[0].v=bitmapHeight/(float)backbufferHeight_; 00412 00413 quad[1].x=x1-0.5f; 00414 quad[1].y=y2-0.5f; 00415 quad[1].z=0; 00416 quad[1].rhw=0.5f; 00417 quad[1].color=color; 00418 quad[1].u=0; 00419 quad[1].v=bitmapHeight/(float)backbufferHeight_; 00420 00421 quad[2].x=x2-0.5f; 00422 quad[2].y=y1-0.5f; 00423 quad[2].z=0; 00424 quad[2].rhw=0.5f; 00425 quad[2].color=color; 00426 quad[2].u=bitmapWidth/(float)backbufferWidth_; 00427 quad[2].v=0; 00428 00429 quad[3].x=x1-0.5f; 00430 quad[3].y=y1-0.5f; 00431 quad[3].z=0; 00432 quad[3].rhw=0.5f; 00433 quad[3].color=color; 00434 quad[3].u=0; 00435 quad[3].v=0; 00436 00437 HRESULT result=S_OK; 00438 00439 00440 result=device_->SetTexture(0,backbuffer2_); 00441 if (FAILED(result)) 00442 { 00443 DebugPrint(("SetTexture failed\n")); 00444 return false; 00445 } 00446 00447 result=device_->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); 00448 if (FAILED(result)) 00449 { 00450 DebugPrint(("SetFVF failed\n")); 00451 return false; 00452 } 00453 00454 00455 result=device_->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1); 00456 if (FAILED(result)) 00457 { 00458 DebugPrint(("SetFVF failed\n")); 00459 return false; 00460 } 00461 00462 result=device_->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP,2,quad,sizeof(Vertex)); 00463 if (FAILED(result)) 00464 { 00465 DebugPrint(("DrawPrimitiveUP\n")); 00466 return false; 00467 } 00468 00469 00470 return true; 00471 } 00472 00473 00474 //*** SetInterpolationMode *** 00475 00476 void Platform_Win32_Screen_D3D9::SetInterpolationMode(bool enabled) 00477 { 00478 if (interpolationMode_==enabled) 00479 { 00480 return; 00481 } 00482 00483 interpolationMode_=enabled; 00484 00485 // Use the right type of filtering for the requested interpolation mode 00486 if (interpolationMode_) 00487 { 00488 device_->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR); 00489 device_->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR); 00490 } 00491 else 00492 { 00493 device_->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_POINT); 00494 device_->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_POINT); 00495 } 00496 } 00497 00498 00499 //*** CreateBackBuffers *** 00500 00501 bool Platform_Win32_Screen_D3D9::CreateBackBuffers(int width, int height) 00502 { 00503 if (backbuffer1_) 00504 { 00505 backbuffer1_->Release(); 00506 backbuffer1_=0; 00507 } 00508 00509 if (backbuffer2_) 00510 { 00511 backbuffer2_->Release(); 00512 backbuffer2_=0; 00513 } 00514 00515 // Create back buffer 00516 backbufferWidth_=8; 00517 backbufferHeight_=8; 00518 while (backbufferWidth_<width) 00519 { 00520 backbufferWidth_*=2; 00521 } 00522 while (backbufferHeight_<height) 00523 { 00524 backbufferHeight_*=2; 00525 } 00526 00527 D3DCAPS9 caps; 00528 device_->GetDeviceCaps(&caps); 00529 if (caps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) 00530 { 00531 HRESULT ret=device_->CreateTexture(backbufferWidth_,backbufferHeight_,1,D3DUSAGE_DYNAMIC,D3DFMT_R5G6B5,D3DPOOL_DEFAULT,&backbuffer1_,0); 00532 if (FAILED(ret)) 00533 { 00534 DebugPrint(("Dynamic textures not supported, using static textures\n")); 00535 ret=device_->CreateTexture(backbufferWidth_,backbufferHeight_,1,0,D3DFMT_R5G6B5,D3DPOOL_MANAGED,&backbuffer1_,0); 00536 if (FAILED(ret)) 00537 { 00538 DebugPrint(("Couldn't create backbuffer1\n")); 00539 return false; 00540 } 00541 ret=device_->CreateTexture(backbufferWidth_,backbufferHeight_,1,0,D3DFMT_R5G6B5,D3DPOOL_MANAGED,&backbuffer2_,0); 00542 if (FAILED(ret)) 00543 { 00544 DebugPrint(("Couldn't create backbuffer2\n")); 00545 return false; 00546 } 00547 } 00548 else 00549 { 00550 ret=device_->CreateTexture(backbufferWidth_,backbufferHeight_,1,D3DUSAGE_DYNAMIC,D3DFMT_R5G6B5,D3DPOOL_DEFAULT,&backbuffer2_,0); 00551 if (FAILED(ret)) 00552 { 00553 DebugPrint(("Couldn't create backbuffer2\n")); 00554 return false; 00555 } 00556 usingDynamicTexture_=true; 00557 } 00558 } 00559 00560 return true; 00561 } 00562 00563 00564 //*** TransformCursorCoordinates *** 00565 00566 void Platform_Win32_Screen_D3D9::TransformCursorCoordinates(float& x, float& y) 00567 { 00568 if (lastPresentWidth_==0 || lastPresentHeight_==0) 00569 { 00570 return; 00571 } 00572 00573 if (!interpolationMode_) 00574 { 00575 int hscale=screenWidth_/lastPresentWidth_; 00576 int vscale=screenHeight_/lastPresentHeight_; 00577 int pixelScale=max(1,min(hscale,vscale)); 00578 int hborder=max(0,(screenWidth_-pixelScale*lastPresentWidth_)/2); 00579 int vborder=max(0,(screenHeight_-pixelScale*lastPresentHeight_)/2); 00580 00581 x=(x-hborder)/pixelScale; 00582 y=(y-vborder)/pixelScale; 00583 return; 00584 } 00585 00586 float hscale=screenWidth_/(float)lastPresentWidth_; 00587 float vscale=screenHeight_/(float)lastPresentHeight_; 00588 float pixelScale=min(hscale,vscale); 00589 00590 float hborder=(screenWidth_-pixelScale*lastPresentWidth_)/2; 00591 float vborder=(screenHeight_-pixelScale*lastPresentHeight_)/2; 00592 00593 x=(x-hborder)/pixelScale; 00594 y=(y-vborder)/pixelScale; 00595 }
Reproduction/republishing of any material on this site without permission is strictly prohibited.
