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

#include "Debug.hpp"

namespace sw
{
	extern bool forceWindowed;

	FrameBufferGDI::FrameBufferGDI(HWND windowHandle, int width, int height, bool fullscreen, bool topLeftOrigin) : FrameBufferWin(windowHandle, width, height, fullscreen, topLeftOrigin)
	{
		if(!windowed)
		{
			SetWindowPos(windowHandle, HWND_TOPMOST, 0, 0, width, height, SWP_SHOWWINDOW);

			DEVMODE deviceMode;
			deviceMode.dmSize = sizeof(DEVMODE);
			deviceMode.dmPelsWidth= width;
			deviceMode.dmPelsHeight = height;
			deviceMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;

			ChangeDisplaySettings(&deviceMode, CDS_FULLSCREEN);
		}

		init(this->windowHandle);

		destFormat = FORMAT_X8R8G8B8;
	}

	FrameBufferGDI::~FrameBufferGDI()
	{
		release();

		if(!windowed)
		{
			ChangeDisplaySettings(0, 0);

			RECT clientRect;
			RECT windowRect;
			GetClientRect(windowHandle, &clientRect);
			GetWindowRect(windowHandle, &windowRect);
			int windowWidth = width + (windowRect.right - windowRect.left) - (clientRect.right - clientRect.left);
			int windowHeight = height + (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
			int desktopWidth = GetSystemMetrics(SM_CXSCREEN);
			int desktopHeight = GetSystemMetrics(SM_CYSCREEN);
			SetWindowPos(windowHandle, HWND_TOP, desktopWidth / 2 - windowWidth / 2, desktopHeight / 2 - windowHeight / 2, windowWidth, windowHeight, SWP_SHOWWINDOW);
		}
	}

	void *FrameBufferGDI::lock()
	{
		stride = width * 4;

		return locked;
	}

	void FrameBufferGDI::unlock()
	{
	}

	void FrameBufferGDI::flip(void *source, Format sourceFormat, size_t sourceStride)
	{
		blit(source, 0, 0, sourceFormat, sourceStride);
	}

	void FrameBufferGDI::blit(void *source, const Rect *sourceRect, const Rect *destRect, Format sourceFormat, size_t sourceStride)
	{
		copy(source, sourceFormat, sourceStride);

		int sourceLeft = sourceRect ? sourceRect->x0 : 0;
		int sourceTop = sourceRect ? sourceRect->y0 : 0;
		int sourceWidth = sourceRect ? sourceRect->x1 - sourceRect->x0 : width;
		int sourceHeight = sourceRect ? sourceRect->y1 - sourceRect->y0 : height;
		int destLeft = destRect ? destRect->x0 : 0;
		int destTop = destRect ? destRect->y0 : 0;
		int destWidth = destRect ? destRect->x1 - destRect->x0 : bounds.right - bounds.left;
		int destHeight = destRect ? destRect->y1 - destRect->y0 : bounds.bottom - bounds.top;

		StretchBlt(windowContext, destLeft, destTop, destWidth, destHeight, bitmapContext, sourceLeft, sourceTop, sourceWidth, sourceHeight, SRCCOPY);
	}

	void FrameBufferGDI::flip(HWND windowOverride, void *source, Format sourceFormat, size_t sourceStride)
	{
		blit(windowOverride, source, 0, 0, sourceFormat, sourceStride);
	}

	void FrameBufferGDI::blit(HWND windowOverride, void *source, const Rect *sourceRect, const Rect *destRect, Format sourceFormat, size_t sourceStride)
	{
		if(windowed && windowOverride != 0 && windowOverride != bitmapWindow)
		{
			release();
			init(windowOverride);
		}

		blit(source, sourceRect, destRect, sourceFormat, sourceStride);
	}

	void FrameBufferGDI::setGammaRamp(GammaRamp *gammaRamp, bool calibrate)
	{
		SetDeviceGammaRamp(windowContext, gammaRamp);
	}

	void FrameBufferGDI::getGammaRamp(GammaRamp *gammaRamp)
	{
		GetDeviceGammaRamp(windowContext, gammaRamp);
	}

	void FrameBufferGDI::screenshot(void *destBuffer)
	{
		UNIMPLEMENTED();
	}

	bool FrameBufferGDI::getScanline(bool &inVerticalBlank, unsigned int &scanline)
	{
		UNIMPLEMENTED();

		return false;
	}

	void FrameBufferGDI::init(HWND window)
	{
		bitmapWindow = window;

		windowContext = GetDC(window);
		bitmapContext = CreateCompatibleDC(windowContext);

		BITMAPINFO bitmapInfo;
		memset(&bitmapInfo, 0, sizeof(BITMAPINFO));
		bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFO);
		bitmapInfo.bmiHeader.biBitCount = 32;
		bitmapInfo.bmiHeader.biPlanes = 1;
		bitmapInfo.bmiHeader.biHeight = -height;
		bitmapInfo.bmiHeader.biWidth = width;
		bitmapInfo.bmiHeader.biCompression = BI_RGB;

		bitmap = CreateDIBSection(bitmapContext, &bitmapInfo, DIB_RGB_COLORS, &locked, 0, 0);
		SelectObject(bitmapContext, bitmap);

		updateBounds(window);
	}

	void FrameBufferGDI::release()
	{
		SelectObject(bitmapContext, 0);
		DeleteObject(bitmap);
		ReleaseDC(bitmapWindow, windowContext);
		DeleteDC(bitmapContext);
	}
}
