blob: 854d02aa7fbcec1520e3fdb3c7fd7cf11584fa12 [file] [log] [blame]
// 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 "Common/Thread.hpp"
#include "Common/SharedLibrary.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 eglAttachThread()
{
TRACE("()");
egl::Current *current = new egl::Current;
if(current)
{
sw::Thread::setLocalStorage(currentTLS, current);
current->error = EGL_SUCCESS;
current->API = EGL_OPENGL_ES_API;
current->display = EGL_NO_DISPLAY;
current->drawSurface = EGL_NO_SURFACE;
current->readSurface = EGL_NO_SURFACE;
}
}
static void eglDetachThread()
{
TRACE("()");
egl::Current *current = (egl::Current*)sw::Thread::getLocalStorage(currentTLS);
if(current)
{
delete current;
}
}
CONSTRUCTOR static bool eglAttachProcess()
{
TRACE("()");
#if !defined(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;
}
eglAttachThread();
#if defined(_WIN32)
const char *libGLESv2_lib = "libGLESv2.dll";
#else
const char *libGLESv2_lib = "libGLESv2.so.2";
#endif
libGLESv2 = loadLibrary(libGLESv2_lib);
gl::createDevice = (gl::Device*(*)())getProcAddress(libGLESv2, "createDevice");
gl::createContext = (gl::Context *(*)(const egl::Config*, const gl::Context*))getProcAddress(libGLESv2, "glCreateContext");
gl::destroyContext = (void (*)(gl::Context*))getProcAddress(libGLESv2, "glDestroyContext");
gl::makeCurrent = (void (*)(gl::Context*, egl::Display*, egl::Surface*))getProcAddress(libGLESv2, "glMakeCurrent");
gl::getCurrentContext = (gl::Context *(*)())getProcAddress(libGLESv2, "glGetCurrentContext");
gl::getProcAddress = (__eglMustCastToProperFunctionPointerType (*)(const char*))getProcAddress(libGLESv2, "glGetProcAddress");
gl::createBackBuffer = (gl::Image *(*)(int, int, const egl::Config*))getProcAddress(libGLESv2, "createBackBuffer");
gl::createFrameBuffer = (sw::FrameBuffer *(*)(EGLNativeDisplayType, EGLNativeWindowType, int, int))getProcAddress(libGLESv2, "createFrameBuffer");
return libGLESv2 != 0;
}
DESTRUCTOR static void eglDetachProcess()
{
TRACE("()");
eglDetachThread();
sw::Thread::freeLocalStorageKey(currentTLS);
freeLibrary(libGLESv2);
}
#if defined(_WIN32)
extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
{
switch(reason)
{
case DLL_PROCESS_ATTACH:
// MessageBoxA(0, "Attach debugger now and press OK", "SwiftShader loaded", MB_OK);
return eglAttachProcess();
break;
case DLL_THREAD_ATTACH:
eglAttachThread();
break;
case DLL_THREAD_DETACH:
eglDetachThread();
break;
case DLL_PROCESS_DETACH:
eglDetachProcess();
break;
default:
break;
}
return TRUE;
}
#endif
namespace egl
{
static Current *eglGetCurrent(void)
{
Current *current = (Current*)sw::Thread::getLocalStorage(currentTLS);
if(!current)
{
eglAttachThread();
}
return (Current*)sw::Thread::getLocalStorage(currentTLS);
}
void setCurrentError(EGLint error)
{
Current *current = eglGetCurrent();
current->error = error;
}
EGLint getCurrentError()
{
Current *current = eglGetCurrent();
return current->error;
}
void setCurrentAPI(EGLenum API)
{
Current *current = eglGetCurrent();
current->API = API;
}
EGLenum getCurrentAPI()
{
Current *current = eglGetCurrent();
return current->API;
}
void setCurrentDisplay(EGLDisplay dpy)
{
Current *current = eglGetCurrent();
current->display = dpy;
}
EGLDisplay getCurrentDisplay()
{
Current *current = eglGetCurrent();
return current->display;
}
void setCurrentDrawSurface(EGLSurface surface)
{
Current *current = eglGetCurrent();
current->drawSurface = surface;
}
EGLSurface getCurrentDrawSurface()
{
Current *current = eglGetCurrent();
return current->drawSurface;
}
void setCurrentReadSurface(EGLSurface surface)
{
Current *current = eglGetCurrent();
current->readSurface = surface;
}
EGLSurface getCurrentReadSurface()
{
Current *current = eglGetCurrent();
return current->readSurface;
}
}
void error(EGLint errorCode)
{
egl::setCurrentError(errorCode);
switch(errorCode)
{
case EGL_SUCCESS: break;
case EGL_NOT_INITIALIZED: TRACE("\t! Error generated: not initialized\n"); break;
case EGL_BAD_ACCESS: TRACE("\t! Error generated: bad access\n"); break;
case EGL_BAD_ALLOC: TRACE("\t! Error generated: bad alloc\n"); break;
case EGL_BAD_ATTRIBUTE: TRACE("\t! Error generated: bad attribute\n"); break;
case EGL_BAD_CONFIG: TRACE("\t! Error generated: bad config\n"); break;
case EGL_BAD_CONTEXT: TRACE("\t! Error generated: bad context\n"); break;
case EGL_BAD_CURRENT_SURFACE: TRACE("\t! Error generated: bad current surface\n"); break;
case EGL_BAD_DISPLAY: TRACE("\t! Error generated: bad display\n"); break;
case EGL_BAD_MATCH: TRACE("\t! Error generated: bad match\n"); break;
case EGL_BAD_NATIVE_PIXMAP: TRACE("\t! Error generated: bad native pixmap\n"); break;
case EGL_BAD_NATIVE_WINDOW: TRACE("\t! Error generated: bad native window\n"); break;
case EGL_BAD_PARAMETER: TRACE("\t! Error generated: bad parameter\n"); break;
case EGL_BAD_SURFACE: TRACE("\t! Error generated: bad surface\n"); break;
case EGL_CONTEXT_LOST: TRACE("\t! Error generated: context lost\n"); break;
default: TRACE("\t! Error generated: <0x%X>\n", errorCode); break;
}
}
namespace gl
{
Device *(*createDevice)() = 0;
Context *(*createContext)(const egl::Config *config, const Context *shareContext) = 0;
void (*destroyContext)(Context *context) = 0;
void (*bindTexImage)(egl::Surface *surface) = 0;
void (*makeCurrent)(Context *context, egl::Display *display, egl::Surface *surface) = 0;
Context *(*getCurrentContext)() = 0;
__eglMustCastToProperFunctionPointerType (*getProcAddress)(const char *procname) = 0;
Image *(*createBackBuffer)(int width, int height, const egl::Config *config) = 0;
sw::FrameBuffer *(*createFrameBuffer)(EGLNativeDisplayType display, EGLNativeWindowType window, int width, int height) = 0;
}
void *libGLESv2 = 0; // Handle to the libGLESv2 module