Skip to content

Commit

Permalink
renderer: modular render window and context creation
Browse files Browse the repository at this point in the history
  • Loading branch information
TheJJ committed Apr 21, 2015
1 parent 1ee0cf4 commit a7e9b92
Show file tree
Hide file tree
Showing 8 changed files with 397 additions and 90 deletions.
82 changes: 2 additions & 80 deletions cpp/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include <epoxy/gl.h>
#include <FTGL/ftgl.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

#include "callbacks.h"
#include "config.h"
Expand Down Expand Up @@ -84,80 +83,7 @@ Engine::Engine(util::Dir *data_dir, const char *windowtitle)
this->register_input_action(&this->input_handler);
this->input_handler.register_resize_action(this);

if (SDL_Init(SDL_INIT_VIDEO) < 0) {
throw util::Error(MSG(err) << "SDL video initialization: " << SDL_GetError());
} else {
log::log(MSG(info) << "Initialized SDL video subsystems.");
}

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

int32_t window_flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED;
this->window = SDL_CreateWindow(
windowtitle,
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
this->engine_coord_data->window_size.x,
this->engine_coord_data->window_size.y,
window_flags
);

if (this->window == nullptr) {
throw util::Error(MSG(err) << "Failed to create SDL window: " << SDL_GetError());
}

// load support for the PNG image formats, jpg bit: IMG_INIT_JPG
int wanted_image_formats = IMG_INIT_PNG;
int sdlimg_inited = IMG_Init(wanted_image_formats);
if ((sdlimg_inited & wanted_image_formats) != wanted_image_formats) {
throw util::Error(MSG(err) << "Failed to init PNG support: " << IMG_GetError());
}

this->glcontext = SDL_GL_CreateContext(this->window);

if (this->glcontext == nullptr) {
throw util::Error(MSG(err) << "Failed creating OpenGL context: " << SDL_GetError());
}

// check the OpenGL version, for shaders n stuff
if (!epoxy_is_desktop_gl() || epoxy_gl_version() < 21) {
throw util::Error(MSG(err) << "OpenGL 2.1 not available");
}

// to quote the standard doc:
// 'The value gives a rough estimate
// of the largest texture that the GL can handle'
// -> wat?
// anyways, we need at least 1024x1024.
int max_texture_size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
log::log(MSG(dbg) << "Maximum supported texture size: " << max_texture_size);
if (max_texture_size < 1024) {
throw util::Error(MSG(err) << "Maximum supported texture size too small: " << max_texture_size);
}

int max_texture_units;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_texture_units);
log::log(MSG(dbg) << "Maximum supported texture units: " << max_texture_units);
if (max_texture_units < 2) {
throw util::Error(MSG(err) << "Your GPU has too less texture units: " << max_texture_units);
}

// vsync on
SDL_GL_SetSwapInterval(1);

// enable alpha blending
glEnable(GL_BLEND);

// order of drawing relevant for depth
// what gets drawn last is displayed on top.
glDisable(GL_DEPTH_TEST);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
this->window = std::make_unique<renderer::Window>(windowtitle);

// initialize job manager with cpucount-2 worker threads
int number_of_worker_threads = SDL_GetCPUCount() - 2;
Expand All @@ -175,10 +101,6 @@ Engine::Engine(util::Dir *data_dir, const char *windowtitle)

Engine::~Engine() {
delete this->job_manager;
SDL_GL_DeleteContext(glcontext);
SDL_DestroyWindow(window);
IMG_Quit();
SDL_Quit();
}

bool Engine::on_resize(coord::window new_size) {
Expand Down Expand Up @@ -314,7 +236,7 @@ void Engine::loop() {

// the rendering is done
// swap the drawing buffers to actually show the frame
SDL_GL_SwapWindow(window);
this->window->swap();
}
}

Expand Down
14 changes: 4 additions & 10 deletions cpp/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
#include <unordered_map>
#include <vector>

#include <SDL2/SDL.h>

#include "log/log.h"
#include "log/file_logsink.h"
#include "audio/audio_manager.h"
Expand All @@ -20,6 +18,7 @@
#include "handlers.h"
#include "input.h"
#include "job/job_manager.h"
#include "renderer/window.h"
#include "util/dir.h"
#include "util/fps.h"
#include "screenshot.h"
Expand Down Expand Up @@ -306,15 +305,10 @@ class Engine : public ResizeHandler {
std::unordered_map<int, std::unique_ptr<Font>> fonts;

/**
* SDL window where everything is displayed within.
*/
SDL_Window *window;

/**
* SDL OpenGL context, we'll only have one,
* but it would allow having multiple ones.
* The render window. Everything is drawn in here.
* Also contains the context.
*/
SDL_GLContext glcontext;
std::unique_ptr<renderer::Window> window;
};

} // namespace openage
Expand Down
12 changes: 12 additions & 0 deletions cpp/renderer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
add_sources(${PROJECT_NAME}
context.cpp
tests.cpp
window.cpp
)

add_demo_cpp(openage::renderer::tests::renderer_demo "open the render window")


#add_subdirectory(gl2/)
#add_subdirectory(gl3/)
#add_subdirectory(vulkan/)
198 changes: 198 additions & 0 deletions cpp/renderer/context.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
// Copyright 2015-2015 the openage authors. See copying.md for legal info.

#include "window.h"

#include <epoxy/gl.h>
#include <SDL2/SDL.h>

#include "../log/log.h"
#include "../util/error.h"


namespace openage {
namespace renderer {

#if WITH_OPENGL
// TODO: get max available gl version
constexpr int opengl_version_major = 2;
constexpr int opengl_version_minor = 1;
#endif

Context::Context(context_type t)
:
type{t} {
if (this->type == context_type::opengl and not WITH_OPENGL) {
throw util::Error(MSG(err) << "OpenGL support not enabled!");
}
else if (this->type == context_type::vulkan and not WITH_VULKAN) {
throw util::Error(MSG(err) << "Vulkan support not enabled!");
}
else if (this->type == context_type::autodetect) {
// priority: vulkan > opengl
if (WITH_VULKAN) {
this->type = context_type::vulkan;
}
else if (WITH_OPENGL) {
this->type = context_type::opengl;
}
else {
throw util::Error(MSG(err) << "No render context available!");
}
}
else {
throw util::Error(MSG(err) << "Unknown context type requested!");
}
}

Context::~Context() {}

void Context::prepare() {
switch (this->type) {
#if WITH_OPENGL
case context_type::opengl:
this->prepare_gl();
break;
#endif
#if WITH_VULKAN
case context_type::vulkan:
// TODO;
break;
#endif
default:
throw util::Error(MSG(err) << "Unknown context to be prepared!");
};
}

uint32_t Context::get_window_flags() {
switch (this->type) {
#if WITH_OPENGL
case context_type::opengl:
return SDL_WINDOW_OPENGL;
#endif
#if WITH_VULKAN
case context_type::vulkan:
return SDL_WINDOW_VULKAN;
#endif
default:
throw util::Error(MSG(err) << "Unknown context w-flags requested!");
};
}

void Context::create(SDL_Window *window) {
switch (this->type) {
#if WITH_OPENGL
case context_type::opengl:
this->create_gl(window);
break;
#endif
#if WITH_VULKAN
case context_type::vulkan:
// TODO
break;
#endif
default:
throw util::Error(MSG(err) << "Unknown context to be created!");
};
}

void Context::setup() {
switch (this->type) {
#if WITH_OPENGL
case context_type::opengl:
this->setup_gl();
break;
#endif
#if WITH_VULKAN
case context_type::vulkan:
// TODO
break;
#endif
default:
throw util::Error(MSG(err) << "Unknown context to be set up!");
};
}

void Context::destroy() {
switch (this->type) {
#if WITH_OPENGL
case context_type::opengl:
this->destroy_gl();
break;
#endif
#if WITH_VULKAN
case context_type::vulkan:
// TODO
break;
#endif
default:
throw util::Error(MSG(err) << "Unknown context to be set up!");
};
}


#if WITH_OPENGL
void Context::prepare_gl() {
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, opengl_version_major);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, opengl_version_minor);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
}

void Context::create_gl(SDL_Window *window) {
this->glcontext = SDL_GL_CreateContext(window);

if (this->glcontext == nullptr) {
throw util::Error(MSG(err) << "Failed creating OpenGL context: " << SDL_GetError());
}

// check the OpenGL version, for shaders n stuff
int epoxy_glv = opengl_version_major * 10 + opengl_version_minor;
if (not epoxy_is_desktop_gl() or epoxy_gl_version() < epoxy_glv) {
throw util::Error(MSG(err) << "OpenGL "
<< opengl_version_major << "." << opengl_version_minor
<< " not available");
}
}

void Context::setup_gl() {
// to quote the standard doc: 'The value gives a rough estimate of the
// largest texture that the GL can handle'
// -> wat? anyways, we need at least 1024x1024.
int max_texture_size;
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size);
log::log(MSG(dbg) << "Maximum supported texture size: " << max_texture_size);
if (max_texture_size < 1024) {
throw util::Error(MSG(err) << "Maximum supported texture size too small: " << max_texture_size);
}

int max_texture_units;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_texture_units);
log::log(MSG(dbg) << "Maximum supported texture units: " << max_texture_units);
if (max_texture_units < 2) {
throw util::Error(MSG(err) << "Your GPU has too less texture units: " << max_texture_units);
}

// vsync on
SDL_GL_SetSwapInterval(1);

// TODO: move the following statements to some other place.

// enable alpha blending
glEnable(GL_BLEND);

// order of drawing relevant for depth
// what gets drawn last is displayed on top.
glDisable(GL_DEPTH_TEST);

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void Context::destroy_gl() {
SDL_GL_DeleteContext(this->glcontext);
}

#endif

}} // namespace openage::renderer
Loading

0 comments on commit a7e9b92

Please sign in to comment.