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 May 14, 2015
1 parent 639db02 commit db170d0
Show file tree
Hide file tree
Showing 12 changed files with 428 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 @@ -83,80 +82,7 @@ Engine::Engine(util::Dir *data_dir, const char *windowtitle)
// execution list.
this->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 @@ -174,10 +100,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 @@ -326,7 +248,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 "job/job_manager.h"
#include "keybinds/keybind_manager.h"
#include "renderer/window.h"
#include "util/dir.h"
#include "util/fps.h"
#include "screenshot.h"
Expand Down Expand Up @@ -308,15 +307,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
9 changes: 9 additions & 0 deletions cpp/renderer/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
add_sources(${PROJECT_NAME}
context.cpp
tests.cpp
window.cpp
)

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

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

#include "context.h"

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

#if WITH_OPENGL
#include "gl/context.h"
#endif

#if WITH_VULKAN
#include "vulkan/context.h"
#endif


namespace openage {
namespace renderer {

Context::Context() {}
Context::~Context() {}

std::unique_ptr<Context> Context::generate(context_type t) {
if (t == context_type::opengl and not WITH_OPENGL) {
throw util::Error(MSG(err) << "OpenGL support not enabled!");
}
else if (t == context_type::vulkan and not WITH_VULKAN) {
throw util::Error(MSG(err) << "Vulkan support not enabled!");
}
else if (t == context_type::autodetect) {
// priority: vulkan > opengl
if (WITH_VULKAN) {
#if WITH_VULKAN
log::log(MSG(dbg) << "Using Vulkan context...");
return std::make_unique<VulkanContext>();
#endif
}
else if (WITH_OPENGL) {
#if WITH_OPENGL
log::log(MSG(dbg) << "Using OpenGL context...");
return std::make_unique<GLContext>();
#endif
}
else {
throw util::Error(MSG(err) << "No render context available!");
}
}
else {
throw util::Error(MSG(err) << "Unknown context type requested!");
}

throw util::Error(MSG(err) << "Context creation dead code reached! Veeery bad.");
}

}} // namespace openage::renderer
38 changes: 38 additions & 0 deletions cpp/renderer/context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2015-2015 the openage authors. See copying.md for legal info.

#ifndef OPENAGE_RENDERER_CONTEXT_H_
#define OPENAGE_RENDERER_CONTEXT_H_

#include <SDL2/SDL.h>

#include <memory>

#include "../coord/window.h"


namespace openage {
namespace renderer {

enum class context_type {
autodetect,
opengl,
vulkan,
};

class Context {
public:
Context();
virtual ~Context();

static std::unique_ptr<Context> generate(context_type t);

virtual void prepare() = 0;
virtual uint32_t get_window_flags() = 0;
virtual void create(SDL_Window *window) = 0;
virtual void setup() = 0;
virtual void destroy() = 0;
};

}} // namespace openage::renderer

#endif
3 changes: 3 additions & 0 deletions cpp/renderer/gl/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
add_sources(${PROJECT_NAME}
context.cpp
)
92 changes: 92 additions & 0 deletions cpp/renderer/gl/context.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// Copyright 2015-2015 the openage authors. See copying.md for legal info.

#include "../../config.h"
#if WITH_OPENGL

#include "context.h"

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

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

namespace openage {
namespace renderer {

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

GLContext::GLContext() {}
GLContext::~GLContext() {}

uint32_t GLContext::get_window_flags() {
return SDL_WINDOW_OPENGL;
}

void GLContext::prepare() {
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 GLContext::create(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 GLContext::setup() {
// 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 GLContext::destroy() {
SDL_GL_DeleteContext(this->glcontext);
}

}} // namespace openage::renderer

#endif // if WITH_OPENGL
31 changes: 31 additions & 0 deletions cpp/renderer/gl/context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2015-2015 the openage authors. See copying.md for legal info.

#ifndef OPENAGE_RENDERER_GL_CONTEXT_H_
#define OPENAGE_RENDERER_GL_CONTEXT_H_

#include <SDL2/SDL.h>

#include "../context.h"
#include "../../config.h"


namespace openage {
namespace renderer {

class GLContext : public Context {
public:
GLContext();
~GLContext();

SDL_GLContext glcontext;

virtual void prepare();
virtual uint32_t get_window_flags();
virtual void create(SDL_Window *window);
virtual void setup();
virtual void destroy();
};

}} // namespace openage::renderer

#endif
Loading

0 comments on commit db170d0

Please sign in to comment.