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 void *source = backBuffer[0]->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC); // FIXME: External 153 sw::Format format = backBuffer[0]->getInternalFormat(); 154 int stride = backBuffer[0]->getInternalPitchB(); 155 156 POINT point; 157 GetCursorPos(&point); 158 ScreenToClient(window, &point); 159 160 frameBuffer->setCursorPosition(point.x, point.y); 161 162 if(!sourceRect && !destRect) // FIXME: More cases? 163 { 164 frameBuffer->flip(window, source, format, stride); 165 } 166 else // FIXME: Check for SWAPEFFECT_COPY 167 { 168 sw::Rect sRect(0, 0, 0, 0); 169 sw::Rect dRect(0, 0, 0, 0); 170 171 if(sourceRect) 172 { 173 sRect.x0 = sourceRect->left; 174 sRect.y0 = sourceRect->top; 175 sRect.x1 = sourceRect->right; 176 sRect.y1 = sourceRect->bottom; 177 } 178 179 if(destRect) 180 { 181 dRect.x0 = destRect->left; 182 dRect.y0 = destRect->top; 183 dRect.x1 = destRect->right; 184 dRect.y1 = destRect->bottom; 185 } 186 187 frameBuffer->blit(window, source, sourceRect ? &sRect : nullptr, destRect ? &dRect : nullptr, format, stride); 188 } 189 190 backBuffer[0]->unlockInternal(); // FIXME: External 191 192 return D3D_OK; 193 } 194 GetFrontBufferData(IDirect3DSurface9 * destSurface)195 long Direct3DSwapChain9::GetFrontBufferData(IDirect3DSurface9 *destSurface) 196 { 197 CriticalSection cs(device); 198 199 TRACE(""); 200 201 if(!destSurface) 202 { 203 return INVALIDCALL(); 204 } 205 206 sw::Surface *dest = static_cast<Direct3DSurface9*>(destSurface); 207 void *buffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PRIVATE); 208 209 frameBuffer->screenshot(buffer); 210 211 dest->unlockExternal(); 212 213 return D3D_OK; 214 } 215 GetBackBuffer(unsigned int index,D3DBACKBUFFER_TYPE type,IDirect3DSurface9 ** backBuffer)216 long Direct3DSwapChain9::GetBackBuffer(unsigned int index, D3DBACKBUFFER_TYPE type, IDirect3DSurface9 **backBuffer) 217 { 218 CriticalSection cs(device); 219 220 TRACE(""); 221 222 if(!backBuffer/* || type != D3DBACKBUFFER_TYPE_MONO*/) 223 { 224 return INVALIDCALL(); 225 } 226 227 *backBuffer = 0; 228 229 if(index >= 3 || this->backBuffer[index] == 0) 230 { 231 return INVALIDCALL(); 232 } 233 234 *backBuffer = this->backBuffer[index]; 235 this->backBuffer[index]->AddRef(); 236 237 return D3D_OK; 238 } 239 GetRasterStatus(D3DRASTER_STATUS * rasterStatus)240 long Direct3DSwapChain9::GetRasterStatus(D3DRASTER_STATUS *rasterStatus) 241 { 242 CriticalSection cs(device); 243 244 TRACE(""); 245 246 if(!rasterStatus) 247 { 248 return INVALIDCALL(); 249 } 250 251 bool inVerticalBlank; 252 unsigned int scanline; 253 bool supported = frameBuffer->getScanline(inVerticalBlank, scanline); 254 255 if(supported) 256 { 257 rasterStatus->InVBlank = inVerticalBlank; 258 rasterStatus->ScanLine = scanline; 259 } 260 else 261 { 262 return INVALIDCALL(); 263 } 264 265 return D3D_OK; 266 } 267 GetDisplayMode(D3DDISPLAYMODE * displayMode)268 long Direct3DSwapChain9::GetDisplayMode(D3DDISPLAYMODE *displayMode) 269 { 270 CriticalSection cs(device); 271 272 TRACE(""); 273 274 if(!displayMode) 275 { 276 return INVALIDCALL(); 277 } 278 279 device->getAdapterDisplayMode(D3DADAPTER_DEFAULT, displayMode); 280 281 return D3D_OK; 282 } 283 GetDevice(IDirect3DDevice9 ** device)284 long Direct3DSwapChain9::GetDevice(IDirect3DDevice9 **device) 285 { 286 CriticalSection cs(this->device); 287 288 TRACE(""); 289 290 if(!device) 291 { 292 return INVALIDCALL(); 293 } 294 295 this->device->AddRef(); 296 *device = this->device; 297 298 return D3D_OK; 299 } 300 GetPresentParameters(D3DPRESENT_PARAMETERS * presentParameters)301 long Direct3DSwapChain9::GetPresentParameters(D3DPRESENT_PARAMETERS *presentParameters) 302 { 303 CriticalSection cs(device); 304 305 TRACE(""); 306 307 if(!presentParameters) 308 { 309 return INVALIDCALL(); 310 } 311 312 *presentParameters = this->presentParameters; 313 314 return D3D_OK; 315 } 316 reset(D3DPRESENT_PARAMETERS * presentParameters)317 void Direct3DSwapChain9::reset(D3DPRESENT_PARAMETERS *presentParameters) 318 { 319 release(); 320 321 ASSERT(presentParameters->BackBufferCount <= 3); // Maximum of three back buffers 322 323 if(presentParameters->BackBufferCount == 0) 324 { 325 presentParameters->BackBufferCount = 1; 326 } 327 328 if(presentParameters->BackBufferFormat == D3DFMT_UNKNOWN) 329 { 330 D3DDISPLAYMODE displayMode; 331 GetDisplayMode(&displayMode); 332 333 presentParameters->BackBufferFormat = displayMode.Format; 334 } 335 336 D3DDEVICE_CREATION_PARAMETERS creationParameters; 337 device->GetCreationParameters(&creationParameters); 338 339 HWND windowHandle = presentParameters->hDeviceWindow ? presentParameters->hDeviceWindow : creationParameters.hFocusWindow; 340 341 if(presentParameters->Windowed && (presentParameters->BackBufferHeight == 0 || presentParameters->BackBufferWidth == 0)) 342 { 343 RECT rectangle; 344 GetClientRect(windowHandle, &rectangle); 345 346 presentParameters->BackBufferWidth = rectangle.right - rectangle.left; 347 presentParameters->BackBufferHeight = rectangle.bottom - rectangle.top; 348 } 349 350 frameBuffer = createFrameBufferWin(windowHandle, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->Windowed == FALSE, true); 351 352 lockable = presentParameters->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; 353 354 backBuffer[0] = 0; 355 backBuffer[1] = 0; 356 backBuffer[2] = 0; 357 358 for(int i = 0; i < (int)presentParameters->BackBufferCount; i++) 359 { 360 backBuffer[i] = new Direct3DSurface9(device, this, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->BackBufferFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->MultiSampleQuality, lockable, D3DUSAGE_RENDERTARGET); 361 backBuffer[i]->bind(); 362 } 363 364 this->presentParameters = *presentParameters; 365 } 366 release()367 void Direct3DSwapChain9::release() 368 { 369 delete frameBuffer; 370 frameBuffer = 0; 371 372 for(int i = 0; i < 3; i++) 373 { 374 if(backBuffer[i]) 375 { 376 backBuffer[i]->unbind(); 377 backBuffer[i] = 0; 378 } 379 } 380 } 381 setGammaRamp(sw::GammaRamp * gammaRamp,bool calibrate)382 void Direct3DSwapChain9::setGammaRamp(sw::GammaRamp *gammaRamp, bool calibrate) 383 { 384 frameBuffer->setGammaRamp(gammaRamp, calibrate); 385 } 386 getGammaRamp(sw::GammaRamp * gammaRamp)387 void Direct3DSwapChain9::getGammaRamp(sw::GammaRamp *gammaRamp) 388 { 389 frameBuffer->getGammaRamp(gammaRamp); 390 } 391 lockBackBuffer(int index)392 void *Direct3DSwapChain9::lockBackBuffer(int index) 393 { 394 return backBuffer[index]->lockInternal(0, 0, 0, sw::LOCK_READWRITE, sw::PUBLIC); // FIXME: External 395 } 396 unlockBackBuffer(int index)397 void Direct3DSwapChain9::unlockBackBuffer(int index) 398 { 399 backBuffer[index]->unlockInternal(); // FIXME: External 400 } 401 } 402