Direct3DSwapChain9.cpp revision 894018228b0e0bdbd7aa7e8f47d4a9458789ca82
1// SwiftShader Software Renderer 2// 3// Copyright(c) 2005-2011 TransGaming Inc. 4// 5// All rights reserved. No part of this software may be copied, distributed, transmitted, 6// transcribed, stored in a retrieval system, translated into any human or computer 7// language by any means, or disclosed to third parties without the explicit written 8// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express 9// or implied, including but not limited to any patent rights, are granted to you. 10// 11 12#include "Direct3DSwapChain9.hpp" 13 14#include "Direct3DDevice9.hpp" 15#include "Renderer.hpp" 16#include "Timer.hpp" 17#include "Resource.hpp" 18#include "Configurator.hpp" 19#include "Debug.hpp" 20 21#include "FrameBufferDD.hpp" 22#include "FrameBufferGDI.hpp" 23 24namespace D3D9 25{ 26 Direct3DSwapChain9::Direct3DSwapChain9(Direct3DDevice9 *device, D3DPRESENT_PARAMETERS *presentParameters) : device(device), presentParameters(*presentParameters) 27 { 28 frameBuffer = 0; 29 30 for(int i = 0; i < 3; i++) 31 { 32 backBuffer[i] = 0; 33 } 34 35 reset(presentParameters); 36 } 37 38 Direct3DSwapChain9::~Direct3DSwapChain9() 39 { 40 release(); 41 } 42 43 long Direct3DSwapChain9::QueryInterface(const IID &iid, void **object) 44 { 45 CriticalSection cs(device); 46 47 TRACE(""); 48 49 if(iid == IID_IDirect3DSwapChain9 || 50 iid == IID_IUnknown) 51 { 52 AddRef(); 53 *object = this; 54 55 return S_OK; 56 } 57 58 *object = 0; 59 60 return NOINTERFACE(iid); 61 } 62 63 unsigned long Direct3DSwapChain9::AddRef() 64 { 65 TRACE(""); 66 67 return Unknown::AddRef(); 68 } 69 70 unsigned long Direct3DSwapChain9::Release() 71 { 72 TRACE(""); 73 74 return Unknown::Release(); 75 } 76 77 long Direct3DSwapChain9::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion, unsigned long flags) 78 { 79 CriticalSection cs(device); 80 81 TRACE(""); 82 83 #if PERF_PROFILE 84 profiler.nextFrame(); 85 #endif 86 87 #if PERF_HUD 88 sw::Renderer *renderer = device->renderer; 89 90 static int64_t frame = sw::Timer::ticks(); 91 92 int64_t frameTime = sw::Timer::ticks() - frame; 93 frame = sw::Timer::ticks(); 94 95 if(frameTime > 0) 96 { 97 unsigned int *frameBuffer = (unsigned int*)lockBackBuffer(0); // FIXME: Don't assume A8R8G8B8 mode 98 unsigned int stride = backBuffer[0]->getInternalPitchP(); 99 100 int thread; 101 for(thread = 0; thread < renderer->getThreadCount(); thread++) 102 { 103 int64_t drawTime = renderer->getVertexTime(thread) + renderer->getSetupTime(thread) + renderer->getPixelTime(thread); 104 105 int vertexPercentage = sw::clamp((int)(100 * renderer->getVertexTime(thread) / frameTime), 0, 100); 106 int setupPercentage = sw::clamp((int)(100 * renderer->getSetupTime(thread) / frameTime), 0, 100); 107 int pixelPercentage = sw::clamp((int)(100 * renderer->getPixelTime(thread) / frameTime), 0, 100); 108 109 for(int i = 0; i < 100; i++) 110 { 111 frameBuffer[thread * stride + i] = 0x00000000; 112 } 113 114 unsigned int *buffer = frameBuffer; 115 116 for(int i = 0; i < vertexPercentage; i++) 117 { 118 buffer[thread * stride] = 0x000000FF; 119 buffer++; 120 } 121 122 for(int i = 0; i < setupPercentage; i++) 123 { 124 buffer[thread * stride] = 0x0000FF00; 125 buffer++; 126 } 127 128 for(int i = 0; i < pixelPercentage; i++) 129 { 130 buffer[thread * stride] = 0x00FF0000; 131 buffer++; 132 } 133 134 frameBuffer[thread * stride + 100] = 0x00FFFFFF; 135 } 136 137 for(int i = 0; i <= 100; i++) 138 { 139 frameBuffer[thread * stride + i] = 0x00FFFFFF; 140 } 141 142 unlockBackBuffer(0); 143 } 144 145 renderer->resetTimers(); 146 #endif 147 148 HWND window = destWindowOverride ? destWindowOverride : presentParameters.hDeviceWindow; 149 void *source = backBuffer[0]->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); // FIXME: External 150 bool HDR = backBuffer[0]->getInternalFormat() == sw::FORMAT_A16B16G16R16; 151 152 POINT point; 153 GetCursorPos(&point); 154 ScreenToClient(window, &point); 155 156 frameBuffer->setCursorPosition(point.x, point.y); 157 158 if(!sourceRect && !destRect) // FIXME: More cases? 159 { 160 frameBuffer->flip(window, source, HDR); 161 } 162 else // FIXME: Check for SWAPEFFECT_COPY 163 { 164 sw::Rect sRect = {0}; 165 sw::Rect dRect = {0}; 166 167 if(sourceRect) 168 { 169 sRect.left = sourceRect->left; 170 sRect.top = sourceRect->top; 171 sRect.right = sourceRect->right; 172 sRect.bottom = sourceRect->bottom; 173 } 174 175 if(destRect) 176 { 177 dRect.left = destRect->left; 178 dRect.top = destRect->top; 179 dRect.right = destRect->right; 180 dRect.bottom = destRect->bottom; 181 } 182 183 frameBuffer->blit(window, source, sourceRect ? &sRect : 0, destRect ? &dRect : 0, HDR); 184 } 185 186 backBuffer[0]->unlockInternal(); // FIXME: External 187 188 return D3D_OK; 189 } 190 191 long Direct3DSwapChain9::GetFrontBufferData(IDirect3DSurface9 *destSurface) 192 { 193 CriticalSection cs(device); 194 195 TRACE(""); 196 197 if(!destSurface) 198 { 199 return INVALIDCALL(); 200 } 201 202 sw::Surface *dest = static_cast<Direct3DSurface9*>(destSurface); 203 void *buffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PRIVATE); 204 205 frameBuffer->screenshot(buffer); 206 207 dest->unlockExternal(); 208 209 return D3D_OK; 210 } 211 212 long Direct3DSwapChain9::GetBackBuffer(unsigned int index, D3DBACKBUFFER_TYPE type, IDirect3DSurface9 **backBuffer) 213 { 214 CriticalSection cs(device); 215 216 TRACE(""); 217 218 if(!backBuffer/* || type != D3DBACKBUFFER_TYPE_MONO*/) 219 { 220 return INVALIDCALL(); 221 } 222 223 *backBuffer = 0; 224 225 if(index >= 3 || this->backBuffer[index] == 0) 226 { 227 return INVALIDCALL(); 228 } 229 230 *backBuffer = this->backBuffer[index]; 231 this->backBuffer[index]->AddRef(); 232 233 return D3D_OK; 234 } 235 236 long Direct3DSwapChain9::GetRasterStatus(D3DRASTER_STATUS *rasterStatus) 237 { 238 CriticalSection cs(device); 239 240 TRACE(""); 241 242 if(!rasterStatus) 243 { 244 return INVALIDCALL(); 245 } 246 247 bool inVerticalBlank; 248 unsigned int scanline; 249 bool supported = frameBuffer->getScanline(inVerticalBlank, scanline); 250 251 if(supported) 252 { 253 rasterStatus->InVBlank = inVerticalBlank; 254 rasterStatus->ScanLine = scanline; 255 } 256 else 257 { 258 return INVALIDCALL(); 259 } 260 261 return D3D_OK; 262 } 263 264 long Direct3DSwapChain9::GetDisplayMode(D3DDISPLAYMODE *displayMode) 265 { 266 CriticalSection cs(device); 267 268 TRACE(""); 269 270 if(!displayMode) 271 { 272 return INVALIDCALL(); 273 } 274 275 device->getAdapterDisplayMode(D3DADAPTER_DEFAULT, displayMode); 276 277 return D3D_OK; 278 } 279 280 long Direct3DSwapChain9::GetDevice(IDirect3DDevice9 **device) 281 { 282 CriticalSection cs(this->device); 283 284 TRACE(""); 285 286 if(!device) 287 { 288 return INVALIDCALL(); 289 } 290 291 this->device->AddRef(); 292 *device = this->device; 293 294 return D3D_OK; 295 } 296 297 long Direct3DSwapChain9::GetPresentParameters(D3DPRESENT_PARAMETERS *presentParameters) 298 { 299 CriticalSection cs(device); 300 301 TRACE(""); 302 303 if(!presentParameters) 304 { 305 return INVALIDCALL(); 306 } 307 308 *presentParameters = this->presentParameters; 309 310 return D3D_OK; 311 } 312 313 void Direct3DSwapChain9::reset(D3DPRESENT_PARAMETERS *presentParameters) 314 { 315 release(); 316 317 ASSERT(presentParameters->BackBufferCount <= 3); // Maximum of three back buffers 318 319 if(presentParameters->BackBufferCount == 0) 320 { 321 presentParameters->BackBufferCount = 1; 322 } 323 324 if(presentParameters->BackBufferFormat == D3DFMT_UNKNOWN) 325 { 326 D3DDISPLAYMODE displayMode; 327 GetDisplayMode(&displayMode); 328 329 presentParameters->BackBufferFormat = displayMode.Format; 330 } 331 332 D3DDEVICE_CREATION_PARAMETERS creationParameters; 333 device->GetCreationParameters(&creationParameters); 334 335 HWND windowHandle = presentParameters->hDeviceWindow ? presentParameters->hDeviceWindow : creationParameters.hFocusWindow; 336 337 if(presentParameters->Windowed && (presentParameters->BackBufferHeight == 0 || presentParameters->BackBufferWidth == 0)) 338 { 339 RECT rectangle; 340 GetClientRect(windowHandle, &rectangle); 341 342 presentParameters->BackBufferWidth = rectangle.right - rectangle.left; 343 presentParameters->BackBufferHeight = rectangle.bottom - rectangle.top; 344 } 345 346 lockable = presentParameters->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; 347 348 sw::Configurator ini("SwiftShader.ini"); 349 int api = ini.getInteger("Testing", "FrameBufferAPI", 0); 350 351 if(api == 0) 352 { 353 frameBuffer = new sw::FrameBufferDD(windowHandle, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->Windowed == FALSE); 354 } 355 else if(api == 1) 356 { 357 frameBuffer = new sw::FrameBufferGDI(windowHandle, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->Windowed == FALSE); 358 } 359 else ASSERT(false); 360 361 backBuffer[0] = 0; 362 backBuffer[1] = 0; 363 backBuffer[2] = 0; 364 365 for(int i = 0; i < (int)presentParameters->BackBufferCount; i++) 366 { 367 backBuffer[i] = new Direct3DSurface9(device, this, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->BackBufferFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->MultiSampleQuality, lockable, D3DUSAGE_RENDERTARGET); 368 backBuffer[i]->bind(); 369 } 370 371 this->presentParameters = *presentParameters; 372 } 373 374 void Direct3DSwapChain9::release() 375 { 376 delete frameBuffer; 377 frameBuffer = 0; 378 379 for(int i = 0; i < 3; i++) 380 { 381 if(backBuffer[i]) 382 { 383 backBuffer[i]->unbind(); 384 backBuffer[i] = 0; 385 } 386 } 387 } 388 389 void Direct3DSwapChain9::setGammaRamp(sw::GammaRamp *gammaRamp, bool calibrate) 390 { 391 frameBuffer->setGammaRamp(gammaRamp, calibrate); 392 } 393 394 void Direct3DSwapChain9::getGammaRamp(sw::GammaRamp *gammaRamp) 395 { 396 frameBuffer->getGammaRamp(gammaRamp); 397 } 398 399 void *Direct3DSwapChain9::lockBackBuffer(int index) 400 { 401 return backBuffer[index]->lockInternal(0, 0, 0, sw::LOCK_READWRITE, sw::PUBLIC); // FIXME: External 402 } 403 404 void Direct3DSwapChain9::unlockBackBuffer(int index) 405 { 406 backBuffer[index]->unlockInternal(); // FIXME: External 407 } 408} 409