chipd8/source/window.d

202 lines
5.5 KiB
D

module window;
import derelict.sdl2.sdl;
import glad.gl.all;
/**
* Converts an integer representing a colour, for example 0x428bca into a 4 element
* int array for passing to OpenGL.
*/
nothrow @nogc pure
GLfloat[4] to(T : GLfloat[4])(int color, ubyte alpha = 255) {
GLfloat[4] gl_color = [ //mask out r, g, b components from int
cast(float)cast(ubyte)(color>>16)/255,
cast(float)cast(ubyte)(color>>8)/255,
cast(float)cast(ubyte)(color)/255,
cast(float)cast(ubyte)(alpha)/255
];
return gl_color;
} // to!GLfloat[4]
struct Window {
import core.stdc.stdio;
import core.stdc.stdlib;
SDL_Window* window;
SDL_GLContext context;
version(Windows) {
extern(Windows) nothrow @nogc
static void openGLCallbackFunction(
GLenum source, GLenum type,
GLuint id, GLenum severity,
GLsizei length, const (GLchar)* message,
void* userParam)
{
printf("Message: %s \nSource: %s \nType: %s \nID: %d \nSeverity: %s\n\n",
message, to!(char*)(source), to!(char*)(type), id, to!(char*)(severity));
if (severity == GL_DEBUG_SEVERITY_HIGH) {
printf("Aborting...\n");
import core.stdc.stdlib : exit;
exit(-1);
}
} // openGLCallbackFunction
} else {
extern(C) nothrow @nogc
static void openGLCallbackFunction(
GLenum source, GLenum type,
GLuint id, GLenum severity,
GLsizei length, const (GLchar*) message, // TODO: look at why it's GLchar* for non-windows and the other works on windows..
void* userParam)
{
printf("Message: %s \nSource: %s \nType: %s \nID: %d \nSeverity: %s\n\n",
message, to!(char*)(source), to!(char*)(type), id, to!(char*)(severity));
if (severity == GL_DEBUG_SEVERITY_HIGH) {
printf("Aborting...\n");
import core.stdc.stdlib : exit;
exit(-1);
}
} // openGLCallbackFunction
}
void createWindow(int w, int h, const char* title = "Chipd8 Emu") {
assert(w > 0, "window width must be > 0");
assert(h > 0, "window height must be > 0");
// minimum OpenGL 3.3
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 32);
// DEBUGGERING!
SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG);
SDL_Window* new_win = SDL_CreateWindow(title, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, w, h, SDL_WINDOW_OPENGL);
if (new_win == null) {
printf("SDL2 - Window could not be created: %s\n", SDL_GetError());
return;
}
SDL_GLContext new_con = SDL_GL_CreateContext(new_win);
if (new_con == null) {
printf("SDL2 - failed creating OpenGL 3.3 context: %s\n", SDL_GetError());
return;
}
import glad.gl.loader : gladLoadGL;
// Check OpenGL properties
printf("OpenGL loaded\n");
gladLoadGL((const (char)* a) => SDL_GL_GetProcAddress(a));
printf("Vendor: %s\n", glGetString(GL_VENDOR));
printf("Renderer: %s\n", glGetString(GL_RENDERER));
printf("Version: %s\n", glGetString(GL_VERSION));
// enable debuggering
glEnable(GL_DEBUG_OUTPUT);
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
glDebugMessageCallback(&openGLCallbackFunction, null);
//enable all
glDebugMessageControl(
GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, null, true
);
//disable notification messages
glDebugMessageControl(
GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, null, false
);
// assign em yes
window = new_win;
context = new_con;
atexit(SDL_Quit);
} // createWindow
void handleEvent(ref SDL_Event ev) {
} // handleEvent
void renderClear(int colour) {
auto col = to!(float[4])(colour, 255);
glClearColor(col[0], col[1], col[2], col[3]);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} // renderClear
void renderPresent() {
SDL_GL_SwapWindow(window);
} // renderPresent
void mousePos(ref int x, ref int y) {
SDL_GetMouseState(&x, &y);
}
void windowSize(ref int w, ref int h) {
SDL_GetWindowSize(window, &w, &h);
}
void framebufferSize(ref int w, ref int h) {
SDL_GL_GetDrawableSize(window, &w, &h);
}
} // Window
/**
* Converts a GLenum representation of a value to a c string representation,
* for use with debug printing of OpenGL info, from debug callbacks for example.
*/
const (char*) to(T : char*)(GLenum value) {
import glad.gl.enums;
switch (value) {
// sources
case GL_DEBUG_SOURCE_API: return "API";
case GL_DEBUG_SOURCE_WINDOW_SYSTEM: return "Window System";
case GL_DEBUG_SOURCE_SHADER_COMPILER: return "Shader Compiler";
case GL_DEBUG_SOURCE_THIRD_PARTY: return "Third Party";
case GL_DEBUG_SOURCE_APPLICATION: return "Application";
case GL_DEBUG_SOURCE_OTHER: return "Other";
// error types
case GL_DEBUG_TYPE_ERROR: return "Error";
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: return "Deprecated Behaviour";
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: return "Undefined Behaviour";
case GL_DEBUG_TYPE_PORTABILITY: return "Portability";
case GL_DEBUG_TYPE_PERFORMANCE: return "Performance";
case GL_DEBUG_TYPE_MARKER: return "Marker";
case GL_DEBUG_TYPE_PUSH_GROUP: return "Push Group";
case GL_DEBUG_TYPE_POP_GROUP: return "Pop Group";
case GL_DEBUG_TYPE_OTHER: return "Other";
// severity markers
case GL_DEBUG_SEVERITY_HIGH: return "High";
case GL_DEBUG_SEVERITY_MEDIUM: return "Medium";
case GL_DEBUG_SEVERITY_LOW: return "Low";
case GL_DEBUG_SEVERITY_NOTIFICATION: return "Notification";
default: return "(undefined)";
}
} // to!string(GLenum)