/*-------------------------------------------------------------------------
 * drawElements Quality Program Tester Core
 * ----------------------------------------
 *
 * Copyright 2014 The Android Open Source Project
 *
 * 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.
 *
 *//*!
 * \file
 * \brief Win32 EGL native display factory
 *//*--------------------------------------------------------------------*/

#include "tcuWin32EGLNativeDisplayFactory.hpp"

#include "egluDefs.hpp"
#include "tcuWin32Window.hpp"
#include "tcuWin32API.h"
#include "tcuTexture.hpp"
#include "deMemory.h"
#include "deThread.h"
#include "deClock.h"
#include "eglwLibrary.hpp"
#include "eglwEnums.hpp"

// Assume no call translation is needed
DE_STATIC_ASSERT(sizeof(eglw::EGLNativeDisplayType) == sizeof(HDC));
DE_STATIC_ASSERT(sizeof(eglw::EGLNativePixmapType) == sizeof(HBITMAP));
DE_STATIC_ASSERT(sizeof(eglw::EGLNativeWindowType) == sizeof(HWND));

namespace tcu
{
namespace win32
{
namespace
{

using namespace eglw;

enum
{
	DEFAULT_SURFACE_WIDTH		= 400,
	DEFAULT_SURFACE_HEIGHT		= 300,
	WAIT_WINDOW_VISIBLE_MS		= 500	//!< Time to wait before issuing screenshot after changing window visibility (hack for DWM)
};

static const eglu::NativeDisplay::Capability	DISPLAY_CAPABILITIES	= eglu::NativeDisplay::CAPABILITY_GET_DISPLAY_LEGACY;
static const eglu::NativePixmap::Capability		BITMAP_CAPABILITIES		= eglu::NativePixmap::CAPABILITY_CREATE_SURFACE_LEGACY;
static const eglu::NativeWindow::Capability		WINDOW_CAPABILITIES		= (eglu::NativeWindow::Capability)
																		   (eglu::NativeWindow::CAPABILITY_CREATE_SURFACE_LEGACY	|
																		    eglu::NativeWindow::CAPABILITY_GET_SURFACE_SIZE			|
																		    eglu::NativeWindow::CAPABILITY_GET_SCREEN_SIZE			|
																			eglu::NativeWindow::CAPABILITY_READ_SCREEN_PIXELS		|
																		    eglu::NativeWindow::CAPABILITY_SET_SURFACE_SIZE			|
																			eglu::NativeWindow::CAPABILITY_CHANGE_VISIBILITY);

class NativeDisplay : public eglu::NativeDisplay
{
public:
									NativeDisplay			(void);
	virtual							~NativeDisplay			(void) {}

	virtual EGLNativeDisplayType	getLegacyNative			(void)			{ return m_deviceContext;	}
	const eglw::Library&			getLibrary				(void) const	{ return m_library;			}

	HDC								getDeviceContext		(void)			{ return m_deviceContext;	}

private:
	HDC								m_deviceContext;
	eglw::DefaultLibrary			m_library;
};

class NativePixmapFactory : public eglu::NativePixmapFactory
{
public:
								NativePixmapFactory		(void);
								~NativePixmapFactory	(void) {}

	virtual eglu::NativePixmap*	createPixmap			(eglu::NativeDisplay* nativeDisplay, int width, int height) const;
	virtual eglu::NativePixmap*	createPixmap			(eglu::NativeDisplay* nativeDisplay, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, int width, int height) const;
};

class NativePixmap : public eglu::NativePixmap
{
public:
								NativePixmap			(NativeDisplay* nativeDisplay, int width, int height, int bitDepth);
	virtual						~NativePixmap			(void);

	EGLNativePixmapType			getLegacyNative			(void) { return m_bitmap; }

private:
	HBITMAP						m_bitmap;
};

class NativeWindowFactory : public eglu::NativeWindowFactory
{
public:
								NativeWindowFactory		(HINSTANCE instance);
	virtual						~NativeWindowFactory	(void) {}

	virtual eglu::NativeWindow*	createWindow			(eglu::NativeDisplay* nativeDisplay, const eglu::WindowParams& params) const;

private:
	const HINSTANCE				m_instance;
};

class NativeWindow : public eglu::NativeWindow
{
public:
									NativeWindow			(NativeDisplay* nativeDisplay, HINSTANCE instance, const eglu::WindowParams& params);
	virtual							~NativeWindow			(void);

	EGLNativeWindowType				getLegacyNative			(void) { return m_window.getHandle(); }
	virtual IVec2					getSurfaceSize			(void) const;
	virtual IVec2					getScreenSize			(void) const { return getSurfaceSize(); }
	virtual void					processEvents			(void);
	virtual void					setSurfaceSize			(IVec2 size);
	virtual void					setVisibility			(eglu::WindowParams::Visibility visibility);
	virtual void					readScreenPixels		(tcu::TextureLevel* dst) const;

private:
	win32::Window					m_window;
	eglu::WindowParams::Visibility	m_curVisibility;
	deUint64						m_setVisibleTime;		//!< Time window was set visible.
};

// NativeDisplay

NativeDisplay::NativeDisplay (void)
	: eglu::NativeDisplay	(DISPLAY_CAPABILITIES)
	, m_deviceContext		((HDC)EGL_DEFAULT_DISPLAY)
	, m_library				("libEGL.dll")
{
}

// NativePixmap

NativePixmap::NativePixmap (NativeDisplay* nativeDisplay, int width, int height, int bitDepth)
	: eglu::NativePixmap	(BITMAP_CAPABILITIES)
	, m_bitmap				(DE_NULL)
{
	const HDC		deviceCtx	= nativeDisplay->getDeviceContext();
	BITMAPINFO		bitmapInfo;

	memset(&bitmapInfo, 0, sizeof(bitmapInfo));

	if (bitDepth != 24 && bitDepth != 32)
		throw NotSupportedError("Unsupported pixmap bit depth", DE_NULL, __FILE__, __LINE__);

	bitmapInfo.bmiHeader.biSize				= sizeof(bitmapInfo);
	bitmapInfo.bmiHeader.biWidth			= width;
	bitmapInfo.bmiHeader.biHeight			= height;
	bitmapInfo.bmiHeader.biPlanes			= 1;
	bitmapInfo.bmiHeader.biBitCount			= bitDepth;
	bitmapInfo.bmiHeader.biCompression		= BI_RGB;
	bitmapInfo.bmiHeader.biSizeImage		= 0;
	bitmapInfo.bmiHeader.biXPelsPerMeter	= 1;
	bitmapInfo.bmiHeader.biYPelsPerMeter	= 1;
	bitmapInfo.bmiHeader.biClrUsed			= 0;
	bitmapInfo.bmiHeader.biClrImportant		= 0;

	void* bitmapPtr = DE_NULL;
	m_bitmap = CreateDIBSection(deviceCtx, &bitmapInfo, DIB_RGB_COLORS, &bitmapPtr, NULL, 0);

	if (!m_bitmap)
		throw ResourceError("Failed to create bitmap", DE_NULL, __FILE__, __LINE__);
}

NativePixmap::~NativePixmap (void)
{
	DeleteObject(m_bitmap);
}

// NativePixmapFactory

NativePixmapFactory::NativePixmapFactory (void)
	: eglu::NativePixmapFactory	("bitmap", "Win32 Bitmap", BITMAP_CAPABILITIES)
{
}

eglu::NativePixmap* NativePixmapFactory::createPixmap (eglu::NativeDisplay* nativeDisplay, EGLDisplay display, EGLConfig config, const EGLAttrib* attribList, int width, int height) const
{
	const Library&	egl			= nativeDisplay->getLibrary();
	int				redBits		= 0;
	int				greenBits	= 0;
	int				blueBits	= 0;
	int				alphaBits	= 0;
	int				bitSum		= 0;

	DE_ASSERT(display != EGL_NO_DISPLAY);

	egl.getConfigAttrib(display, config, EGL_RED_SIZE,		&redBits);
	egl.getConfigAttrib(display, config, EGL_GREEN_SIZE,	&greenBits);
	egl.getConfigAttrib(display, config, EGL_BLUE_SIZE,		&blueBits);
	egl.getConfigAttrib(display, config, EGL_ALPHA_SIZE,	&alphaBits);
	EGLU_CHECK_MSG(egl, "eglGetConfigAttrib()");

	bitSum = redBits+greenBits+blueBits+alphaBits;

	return new NativePixmap(dynamic_cast<NativeDisplay*>(nativeDisplay), width, height, bitSum);
}

eglu::NativePixmap* NativePixmapFactory::createPixmap (eglu::NativeDisplay* nativeDisplay, int width, int height) const
{
	const int defaultDepth = 32;
	return new NativePixmap(dynamic_cast<NativeDisplay*>(nativeDisplay), width, height, defaultDepth);
}

// NativeWindowFactory

NativeWindowFactory::NativeWindowFactory (HINSTANCE instance)
	: eglu::NativeWindowFactory	("window", "Win32 Window", WINDOW_CAPABILITIES)
	, m_instance				(instance)
{
}

eglu::NativeWindow* NativeWindowFactory::createWindow (eglu::NativeDisplay* nativeDisplay, const eglu::WindowParams& params) const
{
	return new NativeWindow(dynamic_cast<NativeDisplay*>(nativeDisplay), m_instance, params);
}

// NativeWindow

NativeWindow::NativeWindow (NativeDisplay* nativeDisplay, HINSTANCE instance, const eglu::WindowParams& params)
	: eglu::NativeWindow	(WINDOW_CAPABILITIES)
	, m_window				(instance,
							 params.width	== eglu::WindowParams::SIZE_DONT_CARE ? DEFAULT_SURFACE_WIDTH	: params.width,
							 params.height	== eglu::WindowParams::SIZE_DONT_CARE ? DEFAULT_SURFACE_HEIGHT	: params.height)
	, m_curVisibility		(eglu::WindowParams::VISIBILITY_HIDDEN)
	, m_setVisibleTime		(0)
{
	if (params.visibility != eglu::WindowParams::VISIBILITY_DONT_CARE)
		setVisibility(params.visibility);
}

void NativeWindow::setVisibility (eglu::WindowParams::Visibility visibility)
{
	switch (visibility)
	{
		case eglu::WindowParams::VISIBILITY_HIDDEN:
			m_window.setVisible(false);
			m_curVisibility		= visibility;
			break;

		case eglu::WindowParams::VISIBILITY_VISIBLE:
		case eglu::WindowParams::VISIBILITY_FULLSCREEN:
			// \todo [2014-03-12 pyry] Implement FULLSCREEN, or at least SW_MAXIMIZE.
			m_window.setVisible(true);
			m_curVisibility		= eglu::WindowParams::VISIBILITY_VISIBLE;
			m_setVisibleTime	= deGetMicroseconds();
			break;

		default:
			DE_ASSERT(DE_FALSE);
	}
}

NativeWindow::~NativeWindow (void)
{
}

IVec2 NativeWindow::getSurfaceSize (void) const
{
	return m_window.getSize();
}

void NativeWindow::processEvents (void)
{
	m_window.processEvents();
}

void NativeWindow::setSurfaceSize (IVec2 size)
{
	m_window.setSize(size.x(), size.y());
}

void NativeWindow::readScreenPixels (tcu::TextureLevel* dst) const
{
	HDC			windowDC	= DE_NULL;
	HDC			screenDC	= DE_NULL;
	HDC			tmpDC		= DE_NULL;
	HBITMAP		tmpBitmap	= DE_NULL;
	RECT		rect;

	TCU_CHECK_INTERNAL(m_curVisibility != eglu::WindowParams::VISIBILITY_HIDDEN);

	// Hack for DWM: There is no way to wait for DWM animations to finish, so we just have to wait
	// for a while before issuing screenshot if window was just made visible.
	{
		const deInt64 timeSinceVisibleUs = (deInt64)(deGetMicroseconds()-m_setVisibleTime);

		if (timeSinceVisibleUs < (deInt64)WAIT_WINDOW_VISIBLE_MS*1000)
			deSleep(WAIT_WINDOW_VISIBLE_MS - (deUint32)(timeSinceVisibleUs/1000));
	}

	TCU_CHECK(GetClientRect(m_window.getHandle(), &rect));

	try
	{
		const int			width		= rect.right - rect.left;
		const int			height		= rect.bottom - rect.top;
		BITMAPINFOHEADER	bitmapInfo;

		deMemset(&bitmapInfo, 0, sizeof(bitmapInfo));

		screenDC = GetDC(DE_NULL);
		TCU_CHECK(screenDC);

		windowDC = GetDC(m_window.getHandle());
		TCU_CHECK(windowDC);

		tmpDC = CreateCompatibleDC(screenDC);
		TCU_CHECK(tmpDC != DE_NULL);

		MapWindowPoints(m_window.getHandle(), DE_NULL, (LPPOINT)&rect, 2);

		tmpBitmap = CreateCompatibleBitmap(screenDC, width, height);
		TCU_CHECK(tmpBitmap != DE_NULL);

		TCU_CHECK(SelectObject(tmpDC, tmpBitmap) != DE_NULL);

		TCU_CHECK(BitBlt(tmpDC, 0, 0, width, height, screenDC, rect.left, rect.top, SRCCOPY));


		bitmapInfo.biSize			= sizeof(BITMAPINFOHEADER);
		bitmapInfo.biWidth			= width;
		bitmapInfo.biHeight			= -height;
		bitmapInfo.biPlanes			= 1;
		bitmapInfo.biBitCount		= 32;
		bitmapInfo.biCompression	= BI_RGB;
		bitmapInfo.biSizeImage		= 0;
		bitmapInfo.biXPelsPerMeter	= 0;
		bitmapInfo.biYPelsPerMeter	= 0;
		bitmapInfo.biClrUsed		= 0;
		bitmapInfo.biClrImportant	= 0;

		dst->setStorage(TextureFormat(TextureFormat::BGRA, TextureFormat::UNORM_INT8), width, height);

		TCU_CHECK(GetDIBits(screenDC, tmpBitmap, 0, height, dst->getAccess().getDataPtr(), (BITMAPINFO*)&bitmapInfo, DIB_RGB_COLORS));

		DeleteObject(tmpBitmap);
		tmpBitmap = DE_NULL;

		ReleaseDC(DE_NULL, screenDC);
		screenDC = DE_NULL;

		ReleaseDC(m_window.getHandle(), windowDC);
		windowDC = DE_NULL;

		DeleteDC(tmpDC);
		tmpDC = DE_NULL;
	}
	catch (...)
	{
		if (screenDC)
			ReleaseDC(DE_NULL, screenDC);

		if (windowDC)
			ReleaseDC(m_window.getHandle(), windowDC);

		if (tmpBitmap)
			DeleteObject(tmpBitmap);

		if (tmpDC)
			DeleteDC(tmpDC);

		throw;
	}
}

} // anonymous

EGLNativeDisplayFactory::EGLNativeDisplayFactory (HINSTANCE instance)
	: eglu::NativeDisplayFactory	("win32", "Native Win32 Display", DISPLAY_CAPABILITIES)
	, m_instance					(instance)
{
	m_nativeWindowRegistry.registerFactory(new NativeWindowFactory(m_instance));
	m_nativePixmapRegistry.registerFactory(new NativePixmapFactory());
}

EGLNativeDisplayFactory::~EGLNativeDisplayFactory (void)
{
}

eglu::NativeDisplay* EGLNativeDisplayFactory::createDisplay (const EGLAttrib* attribList) const
{
	DE_UNREF(attribList);
	return new NativeDisplay();
}

} // win32
} // tcu
