180 lines
4.9 KiB
D
180 lines
4.9 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;
|
|
|
|
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
|
|
|
|
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)
|