// SwiftShader Software Renderer
//
// Copyright(c) 2005-2013 TransGaming Inc.
//
// All rights reserved. No part of this software may be copied, distributed, transmitted,
// transcribed, stored in a retrieval system, translated into any human or computer
// language by any means, or disclosed to third parties without the explicit written
// agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
// or implied, including but not limited to any patent rights, are granted to you.
//

// main.cpp: DLL entry point and management of thread-local data.

#include "main.h"

#include "resource.h"
#include "Framebuffer.h"
#include "Surface.h"
#include "Common/Thread.hpp"
#include "common/debug.h"

static sw::Thread::LocalStorageKey currentTLS = TLS_OUT_OF_INDEXES;

#if !defined(_MSC_VER)
#define CONSTRUCTOR __attribute__((constructor))
#define DESTRUCTOR __attribute__((destructor))
#else
#define CONSTRUCTOR
#define DESTRUCTOR
#endif

static void glAttachThread()
{
    TRACE("()");

	gl::Current *current = new gl::Current;

    if(current)
    {
		sw::Thread::setLocalStorage(currentTLS, current);

        current->context = 0;
        current->display = 0;
        current->drawSurface = 0;
        current->readSurface = 0;
    }
}

static void glDetachThread()
{
    TRACE("()");

	gl::Current *current = (gl::Current*)sw::Thread::getLocalStorage(currentTLS);

    if(current)
    {
        delete current;
    }
}

CONSTRUCTOR static bool glAttachProcess()
{
    TRACE("()");

	#if !(ANGLE_DISABLE_TRACE)
        FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");

        if(debug)
        {
            fclose(debug);
            debug = fopen(TRACE_OUTPUT_FILE, "wt");   // Erase
            fclose(debug);
        }
	#endif

	currentTLS = sw::Thread::allocateLocalStorageKey();

    if(currentTLS == TLS_OUT_OF_INDEXES)
    {
        return false;
    }

    glAttachThread();

    return true;
}

DESTRUCTOR static void glDetachProcess()
{
    TRACE("()");

	glDetachThread();

    sw::Thread::freeLocalStorageKey(currentTLS);
}

#if defined(_WIN32)
static INT_PTR CALLBACK DebuggerWaitDialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	RECT rect;

    switch(uMsg)
    {
    case WM_INITDIALOG:
		GetWindowRect(GetDesktopWindow(), &rect);
		SetWindowPos(hwnd, HWND_TOP, rect.right / 2, rect.bottom / 2, 0, 0, SWP_NOSIZE);
		SetTimer(hwnd, 1, 100, NULL);
		return TRUE;
    case WM_COMMAND:
        if(LOWORD(wParam) == IDCANCEL)
		{
			EndDialog(hwnd, 0);
		}
        break;
    case WM_TIMER:
		if(IsDebuggerPresent())
		{
			EndDialog(hwnd, 0);
		}
    }

    return FALSE;
}

static void WaitForDebugger(HINSTANCE instance)
{
    if(!IsDebuggerPresent())
    {
        HRSRC dialog = FindResource(instance, MAKEINTRESOURCE(IDD_DIALOG1), RT_DIALOG);
		DLGTEMPLATE *dialogTemplate = (DLGTEMPLATE*)LoadResource(instance, dialog);
		DialogBoxIndirect(instance, dialogTemplate, NULL, DebuggerWaitDialogProc);
    }
}

extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
{
    switch(reason)
    {
    case DLL_PROCESS_ATTACH:
		if(false)
		{
			WaitForDebugger(instance);
		}
        return glAttachProcess();
        break;
    case DLL_THREAD_ATTACH:
        glAttachThread();
        break;
    case DLL_THREAD_DETACH:
        glDetachThread();
        break;
    case DLL_PROCESS_DETACH:
        glDetachProcess();
        break;
    default:
        break;
    }

    return TRUE;
}
#endif

namespace gl
{
static gl::Current *getCurrent(void)
{
	Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);

	if(!current)
	{
		glAttachThread();
	}

	return (Current*)sw::Thread::getLocalStorage(currentTLS);
}

void makeCurrent(Context *context, Display *display, Surface *surface)
{
    Current *current = getCurrent();

    current->context = context;
    current->display = display;

    if(context && display && surface)
    {
        context->makeCurrent(surface);
    }
}

Context *getContext()
{
    Current *current = getCurrent();

    return current->context;
}

Display *getDisplay()
{
    Current *current = getCurrent();

    return current->display;
}

Device *getDevice()
{
    Context *context = getContext();

    return context ? context->getDevice() : 0;
}

void setCurrentDisplay(Display *dpy)
{
    Current *current = getCurrent();

    current->display = dpy;
}

void setCurrentContext(gl::Context *ctx)
{
	Current *current = getCurrent();

	current->context = ctx;
}

void setCurrentDrawSurface(Surface *surface)
{
    Current *current = getCurrent();

    current->drawSurface = surface;
}

Surface *getCurrentDrawSurface()
{
    Current *current = getCurrent();

    return current->drawSurface;
}

void setCurrentReadSurface(Surface *surface)
{
    Current *current = getCurrent();

    current->readSurface = surface;
}

Surface *getCurrentReadSurface()
{
    Current *current = getCurrent();

    return current->readSurface;
}
}

// Records an error code
void error(GLenum errorCode)
{
    gl::Context *context = gl::getContext();

    if(context)
    {
        switch(errorCode)
        {
        case GL_INVALID_ENUM:
            context->recordInvalidEnum();
            TRACE("\t! Error generated: invalid enum\n");
            break;
        case GL_INVALID_VALUE:
            context->recordInvalidValue();
            TRACE("\t! Error generated: invalid value\n");
            break;
        case GL_INVALID_OPERATION:
            context->recordInvalidOperation();
            TRACE("\t! Error generated: invalid operation\n");
            break;
        case GL_OUT_OF_MEMORY:
            context->recordOutOfMemory();
            TRACE("\t! Error generated: out of memory\n");
            break;
        case GL_INVALID_FRAMEBUFFER_OPERATION:
            context->recordInvalidFramebufferOperation();
            TRACE("\t! Error generated: invalid framebuffer operation\n");
            break;
        default: UNREACHABLE();
        }
    }
}
