Platform_Win32_Screen_DDraw.cpp
Go to the documentation of this file.00001 //*** Platform_Win32_Screen_DDraw.cpp *** 00002 00003 #include "Platform_Win32_Screen_DDraw.h" 00004 00005 00006 #include "Platform_OS.h" 00007 #define Assert(expression,message) if (!(expression)) Platform::GetPlatform_OS()->OutputDebugText(message); 00008 #define DebugPrint(x) Platform::GetPlatform_OS()->OutputDebugText x; 00009 00010 #define WIN32_LEAN_AND_MEAN 00011 #define VC_EXTRALEAN 00012 00013 #define DIRECTDRAW_VERSION 0x0300 00014 #include <ddraw.h> 00015 00016 #pragma comment (lib, "dxguid.lib") 00017 00018 //*** Constructor *** 00019 00020 Platform_Win32_Screen_DDraw::Platform_Win32_Screen_DDraw(struct HWND__* windowHandle, bool fullscreen, int screenWidth, int screenHeight): 00021 windowHandle_(windowHandle), 00022 interpolationMode_(true), 00023 fullscreen_(fullscreen), 00024 screenWidth_(screenWidth), 00025 screenHeight_(screenHeight), 00026 ddrawDLL_(0), 00027 directDraw_(0), 00028 frontBuffer_(0), 00029 backBuffer_(0), 00030 clipper_(0), 00031 canUseAsyncBlt_(false), 00032 pixelFormat16_(true), 00033 previousPresentColor_(0), 00034 previousPresentWidth_(-1), 00035 previousPresentHeight_(-1), 00036 previousPresent_AppliedToBackBuffer_(false), 00037 lastPresentWidth_(0), 00038 lastPresentHeight_(0) 00039 { 00040 } 00041 00042 00043 //*** Setup *** 00044 00045 bool Platform_Win32_Screen_DDraw::Setup() 00046 { 00047 // Create DirectDraw object 00048 ddrawDLL_=LoadLibrary("ddraw.dll"); 00049 if (!ddrawDLL_) 00050 { 00051 DebugPrint(("Couldn't find ddraw.dll\n")); 00052 return false; 00053 } 00054 00055 // Create DirectDraw object 00056 typedef HRESULT (WINAPI *DirectDrawCreateDefinition)( GUID FAR *lpGUID, LPDIRECTDRAW FAR *lplpDD, IUnknown FAR *pUnkOuter ); 00057 DirectDrawCreateDefinition DirectDrawCreate=(DirectDrawCreateDefinition)GetProcAddress((HMODULE)ddrawDLL_, "DirectDrawCreate"); 00058 if (DirectDrawCreate==0) 00059 { 00060 DebugPrint(("Failed to find function entry point in ddraw.dll\n")); 00061 return false; 00062 } 00063 00064 IDirectDraw* ddrawObject=0; 00065 HRESULT ddrval = DirectDrawCreate( 0, &ddrawObject, 0 ); 00066 if (FAILED(ddrval)) 00067 { 00068 DebugPrint(("Failed to create DirectDraw object\n")); 00069 return false; 00070 } 00071 00072 ddrval=ddrawObject->QueryInterface(IID_IDirectDraw2,reinterpret_cast<void**>(&directDraw_)); 00073 ddrawObject->Release(); 00074 if (FAILED(ddrval)) 00075 { 00076 DebugPrint(("Failed to get DirectDraw2 object through QueryInterface\n")); 00077 return false; 00078 } 00079 00080 00081 if (fullscreen_) 00082 { 00083 SetWindowLong(windowHandle_,GWL_STYLE,WS_POPUPWINDOW|WS_VISIBLE); 00084 00085 // Set cooperative level 00086 ddrval = directDraw_->SetCooperativeLevel(windowHandle_,DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN ); 00087 if (FAILED(ddrval)) 00088 { 00089 DebugPrint(("Failed to set cooperative level\n")); 00090 return false; 00091 } 00092 00093 // Set display mode to 16 bits, but keep the same screen resolution 00094 ddrval = directDraw_->SetDisplayMode(screenWidth_, screenHeight_, 16, 60, 0); 00095 if (FAILED(ddrval)) 00096 { 00097 DebugPrint(("Failed to set display mode\n")); 00098 return false; 00099 } 00100 } 00101 else 00102 { 00103 // Set cooperative level 00104 ddrval = directDraw_->SetCooperativeLevel(windowHandle_,DDSCL_NORMAL); 00105 if (FAILED(ddrval)) 00106 { 00107 DebugPrint(("Failed to set cooperative level\n")); 00108 return false; 00109 } 00110 } 00111 00112 // Get pixelformat of screen 00113 DDSURFACEDESC displayMode; 00114 memset(&displayMode,0,sizeof(DDSURFACEDESC)); 00115 displayMode.dwSize=sizeof(DDSURFACEDESC); 00116 ddrval=directDraw_->GetDisplayMode(&displayMode); 00117 if (FAILED(ddrval)) 00118 { 00119 DebugPrint(("Failed to get display mode\n")); 00120 return false; 00121 } 00122 00123 // Check that pixel format is supported 00124 if ((displayMode.ddpfPixelFormat.dwFlags & DDPF_RGB) && displayMode.ddpfPixelFormat.dwRGBBitCount==32) 00125 { 00126 pixelFormat16_=false; 00127 DebugPrint(("32 bit color mode\n")); 00128 if (displayMode.ddpfPixelFormat.dwRBitMask!=0x00ff0000 || 00129 displayMode.ddpfPixelFormat.dwGBitMask!=0x0000ff00 || 00130 displayMode.ddpfPixelFormat.dwBBitMask!=0x000000ff) 00131 { 00132 DebugPrint(("Pixel format is 32 bit, but the bit masks are invalid\n")); 00133 return false; 00134 } 00135 } 00136 else if ((displayMode.ddpfPixelFormat.dwFlags & DDPF_RGB) && displayMode.ddpfPixelFormat.dwRGBBitCount==16) 00137 { 00138 DebugPrint(("16 bit color mode\n")); 00139 pixelFormat16_=true; 00140 if (displayMode.ddpfPixelFormat.dwRBitMask!=0xf800 || 00141 displayMode.ddpfPixelFormat.dwGBitMask!=0x07e0 || 00142 displayMode.ddpfPixelFormat.dwBBitMask!=0x001f) 00143 { 00144 DebugPrint(("Pixel format is 16 bit, but the bit masks are invalid\n")); 00145 return false; 00146 } 00147 } 00148 else 00149 { 00150 DebugPrint(("Pixel format is not 16 ot 32 bit\n")); 00151 return false; 00152 } 00153 00154 // Check if asynchronous blits are supported 00155 DDCAPS ddcaps; 00156 memset(&ddcaps,0,sizeof(ddcaps)); 00157 ddcaps.dwSize=sizeof(ddcaps); 00158 canUseAsyncBlt_=false; 00159 ddrval=directDraw_->GetCaps(&ddcaps,0); 00160 if (SUCCEEDED(ddrval)) 00161 { 00162 if ((ddcaps.dwCaps & DDCAPS_BLTQUEUE)>0) 00163 { 00164 canUseAsyncBlt_=true; 00165 } 00166 } 00167 00168 // Create the primary surface 00169 DDSURFACEDESC ddsd; 00170 memset(&ddsd,0,sizeof(DDSURFACEDESC)); 00171 ddsd.dwSize = sizeof(ddsd); 00172 /* if (fullscreen_) 00173 { 00174 // Create the primary surface with one back buffer. 00175 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; 00176 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; 00177 ddsd.dwBackBufferCount = 1; 00178 } 00179 else 00180 */ { 00181 // Create simple primary surface 00182 ddsd.dwFlags = DDSD_CAPS ; 00183 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; 00184 } 00185 00186 ddrval = directDraw_->CreateSurface(&ddsd, &frontBuffer_, 0); 00187 if (FAILED(ddrval)) 00188 { 00189 DebugPrint(("Failed to create direct draw front buffer\n")); 00190 return false; 00191 } 00192 00193 00194 // Set up clipper for primary surface 00195 if (!fullscreen_) 00196 { 00197 ddrval = directDraw_->CreateClipper( 0, &clipper_, 0 ); 00198 if (FAILED(ddrval)) 00199 { 00200 DebugPrint(("Failed to create clipper\n")); 00201 return false; 00202 } 00203 00204 ddrval = clipper_->SetHWnd( 0, windowHandle_); 00205 if (FAILED(ddrval)) 00206 { 00207 DebugPrint(("Failed to set clipper window\n")); 00208 return false; 00209 } 00210 00211 ddrval = frontBuffer_->SetClipper(clipper_); 00212 if (FAILED(ddrval)) 00213 { 00214 DebugPrint(("Failed to assign clipper to primary surface\n")); 00215 return false; 00216 } 00217 } 00218 00219 00220 // Create back buffer 00221 /* if (fullscreen_) 00222 { 00223 DDSCAPS ddscaps; 00224 MemSet(&ddscaps,0,sizeof(DDSCAPS)); 00225 ddscaps.dwCaps = DDSCAPS_BACKBUFFER; 00226 ddrval = frontBuffer_->GetAttachedSurface(&ddscaps, &backBuffer_); 00227 if (FAILED(ddrval)) 00228 { 00229 DebugPrint(("Failed to retrieve back buffer\n")); 00230 Terminate(); 00231 return false; 00232 } 00233 } 00234 else 00235 */ { 00236 DWORD capsFlags=DDSCAPS_OFFSCREENPLAIN; 00237 ddsd.dwSize = sizeof( ddsd ); 00238 ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT; 00239 ddsd.ddsCaps.dwCaps = capsFlags; 00240 ddsd.dwWidth=screenWidth_; 00241 ddsd.dwHeight=screenHeight_; 00242 ddsd.ddpfPixelFormat=displayMode.ddpfPixelFormat; 00243 ddrval = directDraw_->CreateSurface( &ddsd, &backBuffer_, 0 ); 00244 if (FAILED(ddrval)) 00245 { 00246 DebugPrint(("Failed to create back buffer\n")); 00247 return false; 00248 } 00249 } 00250 00251 bool result=ClearBackBuffer(0,0,screenWidth_,screenHeight_,0); 00252 if (!result) 00253 { 00254 return false; 00255 } 00256 00257 return true; 00258 } 00259 00260 00261 //*** Destructor *** 00262 00263 Platform_Win32_Screen_DDraw::~Platform_Win32_Screen_DDraw() 00264 { 00265 if (clipper_) 00266 { 00267 clipper_->Release(); 00268 } 00269 if (backBuffer_) 00270 { 00271 backBuffer_->Release(); 00272 } 00273 if (frontBuffer_) 00274 { 00275 frontBuffer_->Release(); 00276 } 00277 00278 if (directDraw_) 00279 { 00280 directDraw_->Release(); 00281 } 00282 00283 if (ddrawDLL_) 00284 { 00285 FreeLibrary((HMODULE)ddrawDLL_); 00286 } 00287 00288 if (fullscreen_) 00289 { 00290 SetWindowLong(windowHandle_,GWL_STYLE,WS_OVERLAPPEDWINDOW | WS_VISIBLE ); 00291 } 00292 } 00293 00294 00295 //*** Present *** 00296 00297 bool Platform_Win32_Screen_DDraw::Present(unsigned short* bitmapData, int bitmapWidth, int bitmapHeight, unsigned short modulate, unsigned short backgroundColor) 00298 { 00299 lastPresentWidth_=bitmapWidth; 00300 lastPresentHeight_=bitmapHeight; 00301 00302 // Check if we need to clear the borders 00303 bool clearBorders=false; 00304 if (previousPresentColor_!=backgroundColor || previousPresentWidth_==-1 || previousPresentHeight_==-1 || 00305 bitmapWidth<previousPresentWidth_ || bitmapHeight<previousPresentHeight_) 00306 { 00307 clearBorders=true; 00308 } 00309 00310 previousPresentColor_=backgroundColor; 00311 previousPresentWidth_=bitmapWidth; 00312 previousPresentHeight_=bitmapHeight; 00313 00314 // Copy data from Bitmap to video memory 00315 if (interpolationMode_) 00316 { 00317 bool result=CopyBitmapToBackBufferInterpolation(bitmapData,bitmapWidth,bitmapHeight,modulate); 00318 if (!result) 00319 { 00320 return false; 00321 } 00322 } 00323 else 00324 { 00325 bool result=CopyBitmapToBackBufferNoInterpolation(bitmapData,bitmapWidth,bitmapHeight,modulate,backgroundColor,clearBorders); 00326 if (!result) 00327 { 00328 return false; 00329 } 00330 } 00331 00332 //if (fullscreen_) 00333 { 00334 // Wait for vertical blank 00335 HRESULT ddrval = directDraw_->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN,0); 00336 if (FAILED(ddrval)) 00337 { 00338 DebugPrint(("WaitForVerticalBlank failed\n")); 00339 return false; 00340 } 00341 } 00342 00343 // Copy data from offscreen surface to screen 00344 if (interpolationMode_) 00345 { 00346 bool result=CopyBackBufferToFrontBufferInterpolation(min(bitmapWidth,screenWidth_),min(bitmapHeight,screenHeight_),backgroundColor,clearBorders); 00347 if (!result) 00348 { 00349 return false; 00350 } 00351 } 00352 else 00353 { 00354 bool result=CopyBackBufferToFrontBufferNoInterpolation(); 00355 if (!result) 00356 { 00357 return false; 00358 } 00359 } 00360 00361 00362 return true; 00363 } 00364 00365 00366 //*** CopyBitmapToBackBufferNoInterpolation *** 00367 00368 bool Platform_Win32_Screen_DDraw::CopyBitmapToBackBufferNoInterpolation(unsigned short* bitmapData, int bitmapWidth, int bitmapHeight, unsigned short modulate, unsigned short backgroundColor, bool clearBorders) 00369 { 00370 int width=bitmapWidth; 00371 int height=bitmapHeight; 00372 00373 unsigned int destWidth=screenWidth_; 00374 unsigned int destHeight=screenHeight_; 00375 int rowSize=sizeof(unsigned short)*width; 00376 00377 int hscale=destWidth/width; 00378 int vscale=destHeight/height; 00379 int pixelScale=min(hscale,vscale); 00380 00381 int hborder=destWidth-pixelScale*width; 00382 int vborder=destHeight-pixelScale*height; 00383 int x1=(destWidth-pixelScale*width)/2; 00384 int y1=(destHeight-pixelScale*height)/2; 00385 int x2=x1+pixelScale*width; 00386 int y2=y1+pixelScale*height; 00387 00388 // clear out and reset surface description 00389 DDSURFACEDESC ddsd; 00390 memset(&ddsd,0,sizeof(ddsd)); 00391 ddsd.dwSize = sizeof(ddsd); 00392 RECT rect; 00393 rect.left=x1; 00394 rect.top=y1; 00395 rect.right=x2; 00396 rect.bottom=y2; 00397 00398 HRESULT ddrval=backBuffer_->Lock(&rect,&ddsd,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY | DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT,0); 00399 while (ddrval==DDERR_SURFACELOST) 00400 { 00401 ddrval=backBuffer_->Restore(); 00402 if (FAILED(ddrval)) 00403 { 00404 DebugPrint(("Couldn't restore back buffer\n")); 00405 return false; 00406 } 00407 ddrval=backBuffer_->Lock(&rect,&ddsd,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY | DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT,0); 00408 } 00409 if (FAILED(ddrval)) 00410 { 00411 DebugPrint(("Couldn't lock back buffer\n")); 00412 return false; 00413 } 00414 if (!(ddsd.dwFlags&(DDSD_LPSURFACE|DDSD_PITCH))) 00415 { 00416 DebugPrint(("Back buffer not valid\n")); 00417 return false; 00418 } 00419 00420 if (pixelFormat16_) 00421 { 00422 unsigned short* data=static_cast<unsigned short*>(ddsd.lpSurface); 00423 unsigned int pitch=ddsd.lPitch; 00424 unsigned short* src=static_cast<unsigned short*>(bitmapData); 00425 int conversionBufferPitchDelta=pitch/2-width; 00426 00427 if (pixelScale==1 && pixelFormat16_ && modulate==0xffff) 00428 { 00429 if (conversionBufferPitchDelta!=0) 00430 { 00431 conversionBufferPitchDelta+=width; 00432 for (int y=0; y<height; y++) 00433 { 00434 memcpy(data,src,rowSize); 00435 src+=width; 00436 data+=conversionBufferPitchDelta; 00437 } 00438 } 00439 else 00440 { 00441 memcpy(data,src,sizeof(unsigned short)*width*height); 00442 } 00443 } 00444 else 00445 { 00446 for (int y=0; y<height; y++) 00447 { 00448 for (int x=0; x<width; x++) 00449 { 00450 unsigned short pixel=*src; 00451 if (modulate!=0xffff) 00452 { 00453 pixel=RGBModulate16(pixel,modulate); 00454 } 00455 src++; 00456 for (int py=0; py<pixelScale; py++) 00457 { 00458 for (int px=0; px<pixelScale; px++) 00459 { 00460 data[px+py*(conversionBufferPitchDelta+width)]=pixel; 00461 } 00462 } 00463 data+=pixelScale; 00464 } 00465 data+=conversionBufferPitchDelta*pixelScale; 00466 } 00467 } 00468 } 00469 else if (!pixelFormat16_) 00470 { 00471 unsigned int* data=static_cast<unsigned int*>(ddsd.lpSurface); 00472 unsigned int pitch=ddsd.lPitch; 00473 unsigned short* src=static_cast<unsigned short*>(bitmapData); 00474 int conversionBufferPitchDelta=pitch/4-width; 00475 for (int y=0; y<height; y++) 00476 { 00477 for (int x=0; x<width; x++) 00478 { 00479 unsigned short pixel=*src; 00480 if (modulate!=0xffff) 00481 { 00482 pixel=RGBModulate16(pixel,modulate); 00483 } 00484 src++; 00485 for (int py=0; py<pixelScale; py++) 00486 { 00487 for (int px=0; px<pixelScale; px++) 00488 { 00489 data[px+py*(conversionBufferPitchDelta+width)]=RGB16TO32(pixel); 00490 } 00491 } 00492 data+=pixelScale; 00493 } 00494 data+=conversionBufferPitchDelta*pixelScale; 00495 } 00496 } 00497 ddrval=backBuffer_->Unlock(ddsd.lpSurface); 00498 if (FAILED(ddrval)) 00499 { 00500 DebugPrint(("Failed to unlock back buffer\n")); 00501 return false; 00502 } 00503 00504 00505 if (clearBorders || !previousPresent_AppliedToBackBuffer_) 00506 { 00507 if (vborder) 00508 { 00509 bool result=ClearBackBuffer(0,0,destWidth,vborder/2,backgroundColor); 00510 if (!result) 00511 { 00512 return false; 00513 } 00514 result=ClearBackBuffer(0,screenHeight_-vborder/2-1,destWidth,screenHeight_,backgroundColor); 00515 if (!result) 00516 { 00517 return false; 00518 } 00519 } 00520 if (hborder) 00521 { 00522 bool result=ClearBackBuffer(0,vborder/2,hborder/2,screenHeight_-vborder/2,backgroundColor); 00523 if (!result) 00524 { 00525 return false; 00526 } 00527 result=ClearBackBuffer(screenWidth_-hborder/2,vborder/2,screenWidth_,screenHeight_-vborder/2,backgroundColor); 00528 if (!result) 00529 { 00530 return false; 00531 } 00532 } 00533 if (clearBorders) 00534 { 00535 previousPresent_AppliedToBackBuffer_=false; 00536 } 00537 else 00538 { 00539 previousPresent_AppliedToBackBuffer_=true; 00540 } 00541 } 00542 00543 return true; 00544 } 00545 00546 00547 //*** CopyBitmapToBackBufferInterpolation *** 00548 00549 bool Platform_Win32_Screen_DDraw::CopyBitmapToBackBufferInterpolation(unsigned short* bitmapData, int bitmapWidth, int bitmapHeight, unsigned short modulate) 00550 { 00551 int width=bitmapWidth; 00552 int height=bitmapHeight; 00553 00554 int x1=0; 00555 int y1=0; 00556 int x2=min(width,screenWidth_); 00557 int y2=min(height,screenHeight_); 00558 00559 // clear out and reset surface description 00560 DDSURFACEDESC ddsd; 00561 memset(&ddsd,0,sizeof(ddsd)); 00562 ddsd.dwSize = sizeof(ddsd); 00563 RECT rect; 00564 rect.left=x1; 00565 rect.top=y1; 00566 rect.right=x2; 00567 rect.bottom=y2; 00568 00569 HRESULT ddrval=backBuffer_->Lock(&rect,&ddsd,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY | DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT,0); 00570 while (ddrval==DDERR_SURFACELOST) 00571 { 00572 ddrval=backBuffer_->Restore(); 00573 if (FAILED(ddrval)) 00574 { 00575 DebugPrint(("Couldn't restore back buffer\n")); 00576 return false; 00577 } 00578 ddrval=backBuffer_->Lock(&rect,&ddsd,DDLOCK_SURFACEMEMORYPTR | DDLOCK_WRITEONLY | DDLOCK_DISCARDCONTENTS | DDLOCK_WAIT,0); 00579 } 00580 if (FAILED(ddrval)) 00581 { 00582 DebugPrint(("Couldn't lock back buffer\n")); 00583 return false; 00584 } 00585 if (!(ddsd.dwFlags&(DDSD_LPSURFACE|DDSD_PITCH))) 00586 { 00587 DebugPrint(("Back buffer not valid\n")); 00588 return false; 00589 } 00590 00591 if (pixelFormat16_) 00592 { 00593 unsigned short* dst=static_cast<unsigned short*>(ddsd.lpSurface); 00594 00595 unsigned int pitch=ddsd.lPitch; 00596 unsigned short* src=static_cast<unsigned short*>(bitmapData); 00597 int conversionBufferPitchDelta=pitch/2-min(width,screenWidth_); 00598 00599 if (modulate==0xffff) 00600 { 00601 if (conversionBufferPitchDelta!=0) 00602 { 00603 int rowSize=sizeof(unsigned short)*min(width,screenWidth_); 00604 conversionBufferPitchDelta+=min(width,screenWidth_); 00605 for (int y=0; y<min(height,screenHeight_); y++) 00606 { 00607 memcpy(dst,src,rowSize); 00608 src+=width; 00609 dst+=conversionBufferPitchDelta; 00610 } 00611 } 00612 else 00613 { 00614 memcpy(dst,src,sizeof(unsigned short)*width*height); 00615 } 00616 } 00617 else 00618 { 00619 int sourceDelta=0; 00620 if (width>screenWidth_) 00621 { 00622 sourceDelta=width-screenWidth_; 00623 } 00624 for (int y=0; y<min(height,screenHeight_); y++) 00625 { 00626 for (int x=0; x<min(width,screenWidth_); x++) 00627 { 00628 unsigned short pixel=*src; 00629 pixel=RGBModulate16(pixel,modulate); 00630 *dst=pixel; 00631 src++; 00632 dst++; 00633 } 00634 dst+=conversionBufferPitchDelta; 00635 src+=sourceDelta; 00636 } 00637 } 00638 } 00639 else 00640 { 00641 unsigned int* dst=static_cast<unsigned int*>(ddsd.lpSurface); 00642 unsigned int pitch=ddsd.lPitch; 00643 unsigned short* src=static_cast<unsigned short*>(bitmapData); 00644 int conversionBufferPitchDelta=pitch/4-min(width,screenWidth_); 00645 int sourceDelta=0; 00646 if (width>screenWidth_) 00647 { 00648 sourceDelta=width-screenWidth_; 00649 } 00650 for (int y=0; y<min(height,screenHeight_); y++) 00651 { 00652 for (int x=0; x<min(width,screenWidth_); x++) 00653 { 00654 unsigned short pixel=*src; 00655 if (modulate!=0xffff) 00656 { 00657 pixel=RGBModulate16(pixel,modulate); 00658 } 00659 *dst=RGB16TO32(pixel); 00660 src++; 00661 dst++; 00662 } 00663 dst+=conversionBufferPitchDelta; 00664 src+=sourceDelta; 00665 } 00666 } 00667 ddrval=backBuffer_->Unlock(ddsd.lpSurface); 00668 if (FAILED(ddrval)) 00669 { 00670 DebugPrint(("Failed to unlock back buffer\n")); 00671 return false; 00672 } 00673 00674 00675 return true; 00676 } 00677 00678 00679 //*** CopyBackBufferToFrontBufferNoInterpolation *** 00680 00681 bool Platform_Win32_Screen_DDraw::CopyBackBufferToFrontBufferNoInterpolation() 00682 { 00683 RECT rect; 00684 BOOL retval=GetClientRect(windowHandle_,&rect); 00685 Assert(retval,"Failed to get client rect"); 00686 POINT pt1; 00687 POINT pt2; 00688 pt1.x=rect.left; 00689 pt1.y=rect.top; 00690 pt2.x=rect.right; 00691 pt2.y=rect.bottom; 00692 retval=ClientToScreen(windowHandle_, &pt1 ); 00693 Assert(retval,"ClientToScreen failed!"); 00694 retval=ClientToScreen(windowHandle_, &pt2 ); 00695 Assert(retval,"ClientToScreen failed!"); 00696 rect.left=pt1.x; 00697 rect.top=pt1.y; 00698 rect.right=pt2.x; 00699 rect.bottom=pt2.y; 00700 00701 int sourceWidth=screenWidth_; 00702 int sourceHeight=screenHeight_; 00703 int destWidth=rect.right-rect.left; 00704 int destHeight=rect.bottom-rect.top; 00705 00706 if (sourceWidth>destWidth) 00707 { 00708 sourceWidth=destWidth; 00709 } 00710 00711 if (sourceHeight>destHeight) 00712 { 00713 sourceHeight=destHeight; 00714 } 00715 00716 int hscale=destWidth/sourceWidth; 00717 int vscale=destHeight/sourceHeight; 00718 int pixelScale=hscale; 00719 if (vscale<hscale) 00720 { 00721 pixelScale=vscale; 00722 } 00723 int hborder=destWidth-pixelScale*sourceWidth; 00724 int vborder=destHeight-pixelScale*sourceHeight; 00725 00726 RECT dest=rect; 00727 dest.left+=hborder/2; 00728 dest.top+=vborder/2; 00729 dest.right-=hborder/2; 00730 dest.bottom-=vborder/2; 00731 00732 RECT source; 00733 source.left=0; 00734 source.top=0; 00735 source.right=sourceWidth; 00736 source.bottom=sourceHeight; 00737 00738 // Blit offscreen surface to primary surface 00739 00740 // use DDCAPS_BLTQUEUE to check if we can use DDBLT_ASYNC 00741 DWORD blitFlags= DDBLT_WAIT; 00742 if (canUseAsyncBlt_) 00743 { 00744 blitFlags|=DDBLT_ASYNC; 00745 } 00746 00747 HRESULT ddrval=frontBuffer_->Blt(&dest,backBuffer_,&source, blitFlags,0); 00748 while (ddrval==DDERR_SURFACELOST) 00749 { 00750 ddrval=frontBuffer_->Restore(); 00751 if (FAILED(ddrval)) 00752 { 00753 DebugPrint(("Failed to restore front buffer\n")); 00754 return false; 00755 } 00756 ddrval=backBuffer_->Restore(); 00757 if (FAILED(ddrval)) 00758 { 00759 DebugPrint(("Failed to restore back buffer\n")); 00760 return false; 00761 } 00762 ddrval=frontBuffer_->Blt(&rect,backBuffer_,&source, blitFlags,0); 00763 } 00764 00765 if (FAILED(ddrval)) 00766 { 00767 DebugPrint(("Blt to front buffer failed\n")); 00768 return false; 00769 } 00770 00771 return true; 00772 } 00773 00774 00775 00776 //*** CopyBackBufferToFrontBufferInterpolation *** 00777 00778 bool Platform_Win32_Screen_DDraw::CopyBackBufferToFrontBufferInterpolation(int width, int height, unsigned short backgroundColor, bool clearBorders) 00779 { 00780 float hscale=screenWidth_/(float)width; 00781 float vscale=screenHeight_/(float)height; 00782 float pixelScale=min(hscale,vscale); 00783 00784 float hborder=(screenWidth_-pixelScale*width)/2; 00785 float vborder=(screenHeight_-pixelScale*height)/2; 00786 00787 RECT rect; 00788 BOOL retval=GetClientRect(windowHandle_,&rect); 00789 Assert(retval,"Failed to get client rect"); 00790 POINT pt1; 00791 POINT pt2; 00792 pt1.x=rect.left; 00793 pt1.y=rect.top; 00794 pt2.x=rect.right; 00795 pt2.y=rect.bottom; 00796 retval=ClientToScreen(windowHandle_, &pt1 ); 00797 Assert(retval,"ClientToScreen failed!"); 00798 retval=ClientToScreen(windowHandle_, &pt2 ); 00799 Assert(retval,"ClientToScreen failed!"); 00800 rect.left=pt1.x; 00801 rect.top=pt1.y; 00802 rect.right=pt2.x; 00803 rect.bottom=pt2.y; 00804 00805 RECT dest=rect; 00806 dest.left+=(int)hborder; 00807 dest.top+=(int)vborder; 00808 dest.right-=(int)hborder; 00809 dest.bottom-=(int)vborder; 00810 00811 RECT source; 00812 source.left=0; 00813 source.top=0; 00814 source.right=width; 00815 source.bottom=height; 00816 00817 // Blit offscreen surface to primary surface 00818 00819 // use DDCAPS_BLTQUEUE to check if we can use DDBLT_ASYNC 00820 DWORD blitFlags= DDBLT_WAIT; 00821 if (canUseAsyncBlt_) 00822 { 00823 blitFlags|=DDBLT_ASYNC; 00824 } 00825 00826 HRESULT ddrval=frontBuffer_->Blt(&dest,backBuffer_,&source, blitFlags,0); 00827 while (ddrval==DDERR_SURFACELOST) 00828 { 00829 ddrval=frontBuffer_->Restore(); 00830 if (FAILED(ddrval)) 00831 { 00832 DebugPrint(("Failed to restore front buffer\n")); 00833 return false; 00834 } 00835 ddrval=backBuffer_->Restore(); 00836 if (FAILED(ddrval)) 00837 { 00838 DebugPrint(("Failed to restore back buffer\n")); 00839 return false; 00840 } 00841 ddrval=frontBuffer_->Blt(&rect,backBuffer_,&source, blitFlags,0); 00842 } 00843 00844 if (FAILED(ddrval)) 00845 { 00846 DebugPrint(("Blt to front buffer failed\n")); 00847 return false; 00848 } 00849 00850 DDBLTFX fx; 00851 ZeroMemory(&fx,sizeof(DDBLTFX)); 00852 fx.dwSize=sizeof(DDBLTFX); 00853 if (pixelFormat16_) 00854 { 00855 fx.dwFillColor=backgroundColor; 00856 } 00857 else 00858 { 00859 fx.dwFillColor=RGB16TO32(backgroundColor); 00860 } 00861 00862 if (((int)vborder)>0) 00863 { 00864 RECT dest=rect; 00865 dest.bottom=dest.top+(int)vborder; 00866 frontBuffer_->Blt(&dest,0,0,blitFlags|DDBLT_COLORFILL,&fx); 00867 dest=rect; 00868 dest.top=dest.bottom-(int)vborder; 00869 frontBuffer_->Blt(&dest,0,0,blitFlags|DDBLT_COLORFILL,&fx); 00870 } 00871 if (((int)hborder)>0) 00872 { 00873 RECT dest=rect; 00874 dest.right=dest.left+(int)hborder; 00875 frontBuffer_->Blt(&dest,0,0,blitFlags|DDBLT_COLORFILL,&fx); 00876 dest=rect; 00877 dest.left=dest.right-(int)hborder; 00878 frontBuffer_->Blt(&dest,0,0,blitFlags|DDBLT_COLORFILL,&fx); 00879 } 00880 00881 00882 return true; 00883 } 00884 00885 00886 //*** ClearBackBuffer *** 00887 00888 bool Platform_Win32_Screen_DDraw::ClearBackBuffer(int x1, int y1, int x2, int y2, unsigned short color) 00889 { 00890 RECT rect; 00891 rect.left=x1; 00892 rect.top=y1; 00893 rect.right=x2; 00894 rect.bottom=y2; 00895 00896 DDBLTFX bltfx; 00897 bltfx.dwSize=sizeof(DDBLTFX); 00898 if (pixelFormat16_) 00899 { 00900 bltfx.dwFillColor=color; 00901 } 00902 else 00903 { 00904 bltfx.dwFillColor=RGB16TO32(color); 00905 } 00906 00907 DWORD blitFlags=DDBLT_WAIT | DDBLT_DDFX | DDBLT_COLORFILL; 00908 if (canUseAsyncBlt_) 00909 { 00910 blitFlags|=DDBLT_ASYNC; 00911 } 00912 00913 HRESULT ddrval=backBuffer_->Blt(&rect,0,0,blitFlags,&bltfx); 00914 while (ddrval==DDERR_SURFACELOST) 00915 { 00916 ddrval=backBuffer_->Restore(); 00917 if (FAILED(ddrval)) 00918 { 00919 DebugPrint(("Failed to restore front buffer\n")); 00920 return false; 00921 } 00922 ddrval=backBuffer_->Blt(&rect,0,0,blitFlags,&bltfx); 00923 } 00924 if (FAILED(ddrval)) 00925 { 00926 DebugPrint(("ColorBlt to front buffer failed\n")); 00927 return false; 00928 } 00929 00930 return true; 00931 } 00932 00933 00934 00935 //*** SetInterpolationMode *** 00936 00937 void Platform_Win32_Screen_DDraw::SetInterpolationMode(bool enabled) 00938 { 00939 interpolationMode_=enabled; 00940 } 00941 00942 00943 //*** TransformCursorCoordinates *** 00944 00945 void Platform_Win32_Screen_DDraw::TransformCursorCoordinates(float& x, float& y) 00946 { 00947 if (lastPresentWidth_==0 || lastPresentHeight_==0) 00948 { 00949 return; 00950 } 00951 00952 if (!interpolationMode_) 00953 { 00954 int hscale=screenWidth_/lastPresentWidth_; 00955 int vscale=screenHeight_/lastPresentHeight_; 00956 int pixelScale=max(1,min(hscale,vscale)); 00957 int hborder=max(0,(screenWidth_-pixelScale*lastPresentWidth_)/2); 00958 int vborder=max(0,(screenHeight_-pixelScale*lastPresentHeight_)/2); 00959 00960 x=(x-hborder)/pixelScale; 00961 y=(y-vborder)/pixelScale; 00962 return; 00963 } 00964 00965 float hscale=screenWidth_/(float)lastPresentWidth_; 00966 float vscale=screenHeight_/(float)lastPresentHeight_; 00967 float pixelScale=min(hscale,vscale); 00968 00969 float hborder=(screenWidth_-pixelScale*lastPresentWidth_)/2; 00970 float vborder=(screenHeight_-pixelScale*lastPresentHeight_)/2; 00971 00972 x=(x-hborder)/pixelScale; 00973 y=(y-vborder)/pixelScale; 00974 }
Reproduction/republishing of any material on this site without permission is strictly prohibited.
