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