// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "Direct3DSwapChain8.hpp" #include "Direct3DDevice8.hpp" #include "Config.hpp" #include "Configurator.hpp" #include "Debug.hpp" #include "FrameBufferDD.hpp" #include "FrameBufferGDI.hpp" namespace D3D8 { Direct3DSwapChain8::Direct3DSwapChain8(Direct3DDevice8 *device, D3DPRESENT_PARAMETERS *presentParameters) : device(device), presentParameters(*presentParameters) { frameBuffer = 0; for(int i = 0; i < 3; i++) { backBuffer[i] = 0; } reset(presentParameters); } Direct3DSwapChain8::~Direct3DSwapChain8() { release(); } long Direct3DSwapChain8::QueryInterface(const IID &iid, void **object) { TRACE(""); if(iid == IID_IDirect3DSwapChain8 || iid == IID_IUnknown) { AddRef(); *object = this; return S_OK; } *object = 0; return NOINTERFACE(iid); } unsigned long Direct3DSwapChain8::AddRef() { TRACE(""); return Unknown::AddRef(); } unsigned long Direct3DSwapChain8::Release() { TRACE(""); return Unknown::Release(); } long Direct3DSwapChain8::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion) { TRACE(""); #if PERF_PROFILE profiler.nextFrame(); #endif if(!sourceRect && !destRect) // FIXME: More cases? { frameBuffer->flip(destWindowOverride, backBuffer[0]); } else // TODO: Check for SWAPEFFECT_COPY { sw::Rect sRect(0, 0, 0, 0); sw::Rect dRect(0, 0, 0, 0); if(sourceRect) { sRect.x0 = sourceRect->left; sRect.y0 = sourceRect->top; sRect.x1 = sourceRect->right; sRect.y1 = sourceRect->bottom; } if(destRect) { dRect.x0 = destRect->left; dRect.y0 = destRect->top; dRect.x1 = destRect->right; dRect.y1 = destRect->bottom; } frameBuffer->blit(destWindowOverride, backBuffer[0], sourceRect ? &sRect : nullptr, destRect ? &dRect : nullptr); } return D3D_OK; } long Direct3DSwapChain8::GetBackBuffer(unsigned int index, D3DBACKBUFFER_TYPE type, IDirect3DSurface8 **backBuffer) { TRACE(""); if(!backBuffer/* || type != D3DBACKBUFFER_TYPE_MONO*/) { return INVALIDCALL(); } if(index >= 3 || this->backBuffer[index] == 0) { return INVALIDCALL(); } this->backBuffer[index]->AddRef(); *backBuffer = this->backBuffer[index]; return D3D_OK; } void Direct3DSwapChain8::reset(D3DPRESENT_PARAMETERS *presentParameters) { release(); this->presentParameters = *presentParameters; ASSERT(presentParameters->BackBufferCount <= 3); // Maximum of three back buffers if(presentParameters->BackBufferCount == 0) { presentParameters->BackBufferCount = 1; } D3DDEVICE_CREATION_PARAMETERS creationParameters; device->GetCreationParameters(&creationParameters); HWND windowHandle = presentParameters->hDeviceWindow ? presentParameters->hDeviceWindow : creationParameters.hFocusWindow; int width = 0; int height = 0; if(presentParameters->Windowed && (presentParameters->BackBufferHeight == 0 || presentParameters->BackBufferWidth == 0)) { RECT rectangle; GetClientRect(windowHandle, &rectangle); width = rectangle.right - rectangle.left; height = rectangle.bottom - rectangle.top; } else { width = presentParameters->BackBufferWidth; height = presentParameters->BackBufferHeight; } frameBuffer = createFrameBufferWin(windowHandle, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->Windowed == FALSE, true); lockable = presentParameters->Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; backBuffer[0] = 0; backBuffer[1] = 0; backBuffer[2] = 0; for(int i = 0; i < (int)presentParameters->BackBufferCount; i++) { backBuffer[i] = new Direct3DSurface8(device, this, width, height, presentParameters->BackBufferFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, lockable, D3DUSAGE_RENDERTARGET); backBuffer[i]->bind(); } } void Direct3DSwapChain8::release() { delete frameBuffer; frameBuffer = 0; for(int i = 0; i < 3; i++) { if(backBuffer[i]) { backBuffer[i]->unbind(); backBuffer[i] = 0; } } } void Direct3DSwapChain8::screenshot(void *destBuffer) { frameBuffer->screenshot(destBuffer); } void Direct3DSwapChain8::setGammaRamp(sw::GammaRamp *gammaRamp, bool calibrate) { frameBuffer->setGammaRamp(gammaRamp, calibrate); } void Direct3DSwapChain8::getGammaRamp(sw::GammaRamp *gammaRamp) { frameBuffer->getGammaRamp(gammaRamp); } void *Direct3DSwapChain8::lockBackBuffer(int index) { return backBuffer[index]->lockInternal(0, 0, 0, sw::LOCK_READWRITE, sw::PUBLIC); // FIXME: External } void Direct3DSwapChain8::unlockBackBuffer(int index) { backBuffer[index]->unlockInternal(); // FIXME: External } }