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