// 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 "Direct3DSwapChain9.hpp"

#include "Direct3DDevice9.hpp"
#include "Renderer.hpp"
#include "Timer.hpp"
#include "Resource.hpp"
#include "Configurator.hpp"
#include "Debug.hpp"

#include "FrameBufferDD.hpp"
#include "FrameBufferGDI.hpp"

namespace D3D9
{
	Direct3DSwapChain9::Direct3DSwapChain9(Direct3DDevice9 *device, D3DPRESENT_PARAMETERS *presentParameters) : device(device), presentParameters(*presentParameters)
	{
		frameBuffer = 0;

		for(int i = 0; i < 3; i++)
		{
			backBuffer[i] = 0;
		}

		reset(presentParameters);
	}

	Direct3DSwapChain9::~Direct3DSwapChain9()
	{
		release();
	}

	long Direct3DSwapChain9::QueryInterface(const IID &iid, void **object)
	{
		CriticalSection cs(device);

		TRACE("");

		if(iid == IID_IDirect3DSwapChain9 ||
		   iid == IID_IUnknown)
		{
			AddRef();
			*object = this;

			return S_OK;
		}

		*object = 0;

		return NOINTERFACE(iid);
	}

	unsigned long Direct3DSwapChain9::AddRef()
	{
		TRACE("");

		return Unknown::AddRef();
	}

	unsigned long Direct3DSwapChain9::Release()
	{
		TRACE("");

		return Unknown::Release();
	}

	long Direct3DSwapChain9::Present(const RECT *sourceRect, const RECT *destRect, HWND destWindowOverride, const RGNDATA *dirtyRegion, unsigned long flags)
	{
		CriticalSection cs(device);

		TRACE("");

		#if PERF_PROFILE
			profiler.nextFrame();
		#endif

		#if PERF_HUD
			sw::Renderer *renderer = device->renderer;

			static int64_t frame = sw::Timer::ticks();

			int64_t frameTime = sw::Timer::ticks() - frame;
			frame = sw::Timer::ticks();

			if(frameTime > 0)
			{
				unsigned int *frameBuffer = (unsigned int*)lockBackBuffer(0);   // FIXME: Don't assume A8R8G8B8 mode
				unsigned int stride = backBuffer[0]->getInternalPitchP();

				int thread;
				for(thread = 0; thread < renderer->getThreadCount(); thread++)
				{
					int64_t drawTime = renderer->getVertexTime(thread) + renderer->getSetupTime(thread) + renderer->getPixelTime(thread);

					int vertexPercentage = sw::clamp((int)(100 * renderer->getVertexTime(thread) / frameTime), 0, 100);
					int setupPercentage = sw::clamp((int)(100 * renderer->getSetupTime(thread) / frameTime), 0, 100);
					int pixelPercentage = sw::clamp((int)(100 * renderer->getPixelTime(thread) / frameTime), 0, 100);

					for(int i = 0; i < 100; i++)
					{
						frameBuffer[thread * stride + i] = 0x00000000;
					}

					unsigned int *buffer = frameBuffer;

					for(int i = 0; i < vertexPercentage; i++)
					{
						buffer[thread * stride] = 0x000000FF;
						buffer++;
					}

					for(int i = 0; i < setupPercentage; i++)
					{
						buffer[thread * stride] = 0x0000FF00;
						buffer++;
					}

					for(int i = 0; i < pixelPercentage; i++)
					{
						buffer[thread * stride] = 0x00FF0000;
						buffer++;
					}

					frameBuffer[thread * stride + 100] = 0x00FFFFFF;
				}

				for(int i = 0; i <= 100; i++)
				{
					frameBuffer[thread * stride + i] = 0x00FFFFFF;
				}

				unlockBackBuffer(0);
			}

			renderer->resetTimers();
		#endif

		HWND window = destWindowOverride ? destWindowOverride : presentParameters.hDeviceWindow;
		void *source = backBuffer[0]->lockInternal(0, 0, 0, sw::LOCK_READONLY, sw::PUBLIC);   // FIXME: External
		sw::Format format = backBuffer[0]->getInternalFormat();
		int stride = backBuffer[0]->getInternalPitchB();

		POINT point;
		GetCursorPos(&point);
		ScreenToClient(window, &point);

		frameBuffer->setCursorPosition(point.x, point.y);

		if(!sourceRect && !destRect)   // FIXME: More cases?
		{
			frameBuffer->flip(window, source, format, stride);
		}
		else   // FIXME: 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(window, source, sourceRect ? &sRect : nullptr, destRect ? &dRect : nullptr, format, stride);
		}

		backBuffer[0]->unlockInternal();   // FIXME: External

		return D3D_OK;
	}

	long Direct3DSwapChain9::GetFrontBufferData(IDirect3DSurface9 *destSurface)
	{
		CriticalSection cs(device);

		TRACE("");

		if(!destSurface)
		{
			return INVALIDCALL();
		}

		sw::Surface *dest = static_cast<Direct3DSurface9*>(destSurface);
		void *buffer = dest->lockExternal(0, 0, 0, sw::LOCK_WRITEONLY, sw::PRIVATE);

		frameBuffer->screenshot(buffer);

		dest->unlockExternal();

		return D3D_OK;
	}

	long Direct3DSwapChain9::GetBackBuffer(unsigned int index, D3DBACKBUFFER_TYPE type, IDirect3DSurface9 **backBuffer)
	{
		CriticalSection cs(device);

		TRACE("");

		if(!backBuffer/* || type != D3DBACKBUFFER_TYPE_MONO*/)
		{
			return INVALIDCALL();
		}

		*backBuffer = 0;

		if(index >= 3 || this->backBuffer[index] == 0)
		{
			return INVALIDCALL();
		}

		*backBuffer = this->backBuffer[index];
		this->backBuffer[index]->AddRef();

		return D3D_OK;
	}

	long Direct3DSwapChain9::GetRasterStatus(D3DRASTER_STATUS *rasterStatus)
	{
		CriticalSection cs(device);

		TRACE("");

		if(!rasterStatus)
		{
			return INVALIDCALL();
		}

		bool inVerticalBlank;
		unsigned int scanline;
		bool supported = frameBuffer->getScanline(inVerticalBlank, scanline);

		if(supported)
		{
			rasterStatus->InVBlank = inVerticalBlank;
			rasterStatus->ScanLine = scanline;
		}
		else
		{
			return INVALIDCALL();
		}

		return D3D_OK;
	}

	long Direct3DSwapChain9::GetDisplayMode(D3DDISPLAYMODE *displayMode)
	{
		CriticalSection cs(device);

		TRACE("");

		if(!displayMode)
		{
			return INVALIDCALL();
		}

		device->getAdapterDisplayMode(D3DADAPTER_DEFAULT, displayMode);

		return D3D_OK;
	}

	long Direct3DSwapChain9::GetDevice(IDirect3DDevice9 **device)
	{
		CriticalSection cs(this->device);

		TRACE("");

		if(!device)
		{
			return INVALIDCALL();
		}

		this->device->AddRef();
		*device = this->device;

		return D3D_OK;
	}

	long Direct3DSwapChain9::GetPresentParameters(D3DPRESENT_PARAMETERS *presentParameters)
	{
		CriticalSection cs(device);

		TRACE("");

		if(!presentParameters)
		{
			return INVALIDCALL();
		}

		*presentParameters = this->presentParameters;

		return D3D_OK;
	}

	void Direct3DSwapChain9::reset(D3DPRESENT_PARAMETERS *presentParameters)
	{
		release();

		ASSERT(presentParameters->BackBufferCount <= 3);   // Maximum of three back buffers

		if(presentParameters->BackBufferCount == 0)
		{
			presentParameters->BackBufferCount = 1;
		}

		if(presentParameters->BackBufferFormat == D3DFMT_UNKNOWN)
		{
			D3DDISPLAYMODE displayMode;
			GetDisplayMode(&displayMode);

			presentParameters->BackBufferFormat = displayMode.Format;
		}

		D3DDEVICE_CREATION_PARAMETERS creationParameters;
		device->GetCreationParameters(&creationParameters);

		HWND windowHandle = presentParameters->hDeviceWindow ? presentParameters->hDeviceWindow : creationParameters.hFocusWindow;

		if(presentParameters->Windowed && (presentParameters->BackBufferHeight == 0 || presentParameters->BackBufferWidth == 0))
		{
			RECT rectangle;
			GetClientRect(windowHandle, &rectangle);

			presentParameters->BackBufferWidth = rectangle.right - rectangle.left;
			presentParameters->BackBufferHeight = rectangle.bottom - rectangle.top;
		}

		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 Direct3DSurface9(device, this, presentParameters->BackBufferWidth, presentParameters->BackBufferHeight, presentParameters->BackBufferFormat, D3DPOOL_DEFAULT, presentParameters->MultiSampleType, presentParameters->MultiSampleQuality, lockable, D3DUSAGE_RENDERTARGET);
			backBuffer[i]->bind();
		}

		this->presentParameters = *presentParameters;
	}

	void Direct3DSwapChain9::release()
	{
		delete frameBuffer;
		frameBuffer = 0;

		for(int i = 0; i < 3; i++)
		{
			if(backBuffer[i])
			{
				backBuffer[i]->unbind();
				backBuffer[i] = 0;
			}
		}
	}

	void Direct3DSwapChain9::setGammaRamp(sw::GammaRamp *gammaRamp, bool calibrate)
	{
		frameBuffer->setGammaRamp(gammaRamp, calibrate);
	}

	void Direct3DSwapChain9::getGammaRamp(sw::GammaRamp *gammaRamp)
	{
		frameBuffer->getGammaRamp(gammaRamp);
	}

	void *Direct3DSwapChain9::lockBackBuffer(int index)
	{
		return backBuffer[index]->lockInternal(0, 0, 0, sw::LOCK_READWRITE, sw::PUBLIC);   // FIXME: External
	}

	void Direct3DSwapChain9::unlockBackBuffer(int index)
	{
		backBuffer[index]->unlockInternal();   // FIXME: External
	}
}
