| // 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 | |
| } | |
| } |