Skip to content

Commit fb2d4b7

Browse files
committed
renderer: initially integrated into the engine
used for screenshots and resizing currently
1 parent 821c5e3 commit fb2d4b7

File tree

14 files changed

+206
-114
lines changed

14 files changed

+206
-114
lines changed

libopenage/audio/dynamic_resource.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#include "../engine.h"
66
#include "../log/log.h"
7+
#include "../job/job_manager.h"
78

89
namespace openage {
910
namespace audio {

libopenage/engine.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,21 @@
99
#include <FTGL/ftgl.h>
1010
#include <SDL2/SDL.h>
1111

12-
#include "error/error.h"
13-
#include "log/log.h"
14-
1512
#include "config.h"
13+
#include "error/error.h"
14+
#include "font.h"
1615
#include "game_main.h"
1716
#include "generator.h"
17+
#include "job/job_manager.h"
18+
#include "log/log.h"
1819
#include "texture.h"
1920
#include "util/color.h"
2021
#include "util/fps.h"
2122
#include "util/opengl.h"
2223
#include "util/strings.h"
24+
#include "renderer/renderer.h"
25+
#include "renderer/window.h"
26+
#include "screenshot.h"
2327

2428

2529
/**
@@ -88,14 +92,19 @@ Engine::Engine(util::Dir *data_dir, const char *windowtitle)
8892
// register the engines input manager
8993
this->register_input_action(&this->input_manager);
9094

95+
// create the graphical display
9196
this->window = std::make_unique<renderer::Window>(windowtitle);
97+
this->renderer = std::make_unique<renderer::Renderer>(this->window->get_context());
98+
99+
// renderer has to be notified of window size changes
100+
this->register_resize_action(this->renderer.get());
92101

93102
// initialize job manager with cpucount-2 worker threads
94103
int number_of_worker_threads = SDL_GetCPUCount() - 2;
95104
if (number_of_worker_threads <= 0) {
96105
number_of_worker_threads = 1;
97106
}
98-
this->job_manager = new job::JobManager{number_of_worker_threads};
107+
this->job_manager = std::make_unique<job::JobManager>(number_of_worker_threads);
99108

100109
// initialize audio
101110
auto devices = audio::AudioManager::get_devices();
@@ -112,7 +121,7 @@ Engine::Engine(util::Dir *data_dir, const char *windowtitle)
112121
this->drawing_huds.value = !this->drawing_huds.value;
113122
});
114123
global_input_context.bind(input::action_t::SCREENSHOT, [this](const input::action_arg_t &) {
115-
this->get_screenshot_manager().save_screenshot();
124+
this->get_screenshot_manager()->save_screenshot();
116125
});
117126
global_input_context.bind(input::action_t::TOGGLE_DEBUG_OVERLAY, [this](const input::action_arg_t &) {
118127
this->drawing_debug_overlay.value = !this->drawing_debug_overlay.value;
@@ -150,19 +159,14 @@ Engine::Engine(util::Dir *data_dir, const char *windowtitle)
150159
bind_player_switch(input::action_t::SWITCH_TO_PLAYER_8, 8);
151160
}
152161

153-
Engine::~Engine() {
154-
delete this->job_manager;
155-
}
162+
Engine::~Engine() {}
156163

157164
bool Engine::on_resize(coord::window new_size) {
158165
log::log(MSG(dbg) << "engine window resize to " << new_size.x << "x" << new_size.y);
159166

160167
// update engine window size
161168
this->engine_coord_data->window_size = new_size;
162169

163-
// tell the screenshot manager about the new size
164-
this->screenshot_manager.window_size = new_size;
165-
166170
// update camgame window position, set it to center.
167171
this->engine_coord_data->camgame_window = this->engine_coord_data->window_size / 2;
168172

@@ -173,9 +177,6 @@ bool Engine::on_resize(coord::window new_size) {
173177
glMatrixMode(GL_PROJECTION);
174178
glLoadIdentity();
175179

176-
// update OpenGL viewport: the renderin area
177-
glViewport(0, 0, this->engine_coord_data->window_size.x, this->engine_coord_data->window_size.y);
178-
179180
// set orthographic projection: left, right, bottom, top, near_val, far_val
180181
glOrtho(0, this->engine_coord_data->window_size.x, 0, this->engine_coord_data->window_size.y, 9001, -1);
181182

@@ -387,15 +388,15 @@ Player *Engine::player_focus() const {
387388
}
388389

389390
job::JobManager *Engine::get_job_manager() {
390-
return this->job_manager;
391+
return this->job_manager.get();
391392
}
392393

393394
audio::AudioManager &Engine::get_audio_manager() {
394395
return this->audio_manager;
395396
}
396397

397-
ScreenshotManager &Engine::get_screenshot_manager() {
398-
return this->screenshot_manager;
398+
ScreenshotManager *Engine::get_screenshot_manager() {
399+
return this->screenshot_manager.get();
399400
}
400401

401402
input::InputManager &Engine::get_input_manager() {

libopenage/engine.h

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,33 @@
1414
#include "coord/vec2f.h"
1515
#include "coord/phys3.h"
1616
#include "coord/window.h"
17-
#include "font.h"
1817
#include "handlers.h"
1918
#include "options.h"
2019
#include "input/input_manager.h"
21-
#include "job/job_manager.h"
22-
#include "renderer/window.h"
2320
#include "util/externalprofiler.h"
2421
#include "util/dir.h"
2522
#include "util/fps.h"
26-
#include "screenshot.h"
2723

2824
namespace openage {
2925

3026
class DrawHandler;
3127
class TickHandler;
3228
class ResizeHandler;
3329

34-
class Generator;
35-
class GameSpec;
30+
class Font;
3631
class GameMain;
32+
class GameSpec;
33+
class Generator;
3734
class Player;
35+
class ScreenshotManager;
36+
37+
namespace job {
38+
class JobManager;
39+
}
40+
namespace renderer {
41+
class Renderer;
42+
class Window;
43+
}
3844

3945
struct coord_data {
4046
coord::window window_size{800, 600};
@@ -204,7 +210,7 @@ class Engine : public ResizeHandler, public options::OptionNode {
204210
/**
205211
* return this engine's screenshot manager.
206212
*/
207-
ScreenshotManager &get_screenshot_manager();
213+
ScreenshotManager *get_screenshot_manager();
208214

209215
/**
210216
* return this engine's keybind manager.
@@ -317,7 +323,7 @@ class Engine : public ResizeHandler, public options::OptionNode {
317323
/**
318324
* the engine's screenshot manager.
319325
*/
320-
ScreenshotManager screenshot_manager;
326+
std::unique_ptr<ScreenshotManager> screenshot_manager;
321327

322328
/**
323329
* the engine's audio manager.
@@ -327,8 +333,7 @@ class Engine : public ResizeHandler, public options::OptionNode {
327333
/**
328334
* the engine's job manager, for asynchronous background task queuing.
329335
*/
330-
job::JobManager *job_manager;
331-
336+
std::unique_ptr<job::JobManager> job_manager;
332337

333338
/**
334339
* the engine's keybind manager.
@@ -346,6 +351,11 @@ class Engine : public ResizeHandler, public options::OptionNode {
346351
* Also contains the context.
347352
*/
348353
std::unique_ptr<renderer::Window> window;
354+
355+
/**
356+
* The renderer. Accepts all tasks to be drawn on screen.
357+
*/
358+
std::unique_ptr<renderer::Renderer> renderer;
349359
};
350360

351361
} // namespace openage

libopenage/game_spec.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
// Copyright 2015-2015 the openage authors. See copying.md for legal info.
22

3+
#include "assetmanager.h"
4+
#include "engine.h"
5+
#include "game_spec.h"
36
#include "gamedata/blending_mode.gen.h"
47
#include "gamedata/string_resource.gen.h"
58
#include "gamedata/terrain.gen.h"
9+
#include "job/job_manager.h"
10+
#include "rng/global_rng.h"
611
#include "unit/producer.h"
712
#include "util/strings.h"
8-
#include "rng/global_rng.h"
9-
#include "assetmanager.h"
10-
#include "game_spec.h"
11-
#include "engine.h"
1213

1314
namespace openage {
1415

libopenage/handlers.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010

1111
namespace openage {
1212

13-
class Engine;
14-
1513
/**
1614
* superclass for all possible drawing operations in the game.
1715
*/

libopenage/renderer/context.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,11 @@ std::unique_ptr<Context> Context::generate(context_type t) {
6666
return nullptr;
6767
}
6868

69+
70+
void Context::resize(const coord::window &new_size) {
71+
this->canvas_size = new_size;
72+
this->resize_canvas(this->canvas_size);
73+
}
74+
75+
6976
}} // namespace openage::renderer

libopenage/renderer/context.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
#ifndef OPENAGE_RENDERER_CONTEXT_H_
44
#define OPENAGE_RENDERER_CONTEXT_H_
55

6-
#include <SDL2/SDL.h>
7-
86
#include <memory>
7+
#include <SDL2/SDL.h>
98

9+
#include "../coord/window.h"
1010
#include "shader.h"
1111
#include "texture.h"
1212

@@ -77,6 +77,11 @@ class Context {
7777
*/
7878
virtual void set_feature(context_feature feature, bool on) = 0;
7979

80+
/**
81+
* Save this context's framebuffer as a png screenshot.
82+
*/
83+
virtual void screenshot(const std::string &filename) = 0;
84+
8085
/**
8186
* Register some texture data to the context.
8287
* @returns the newly created Texture handle.
@@ -89,12 +94,26 @@ class Context {
8994
*/
9095
virtual std::shared_ptr<Program> register_program(const ProgramSource &data) = 0;
9196

97+
/**
98+
* Resize the context because the surrounding window size was updated.
99+
*/
100+
void resize(const coord::window &new_size);
92101

93102
protected:
103+
/**
104+
* Perform context-specific calls to resize the drawing canvas.
105+
*/
106+
virtual void resize_canvas(const coord::window &new_size) = 0;
107+
94108
/**
95109
* Type of this context, namely the backend variant.
96110
*/
97111
context_type type;
112+
113+
/**
114+
* Render surface size.
115+
*/
116+
coord::window canvas_size;
98117
};
99118

100119
}} // namespace openage::renderer

libopenage/renderer/opengl/context.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include <epoxy/gl.h>
99
#include <SDL2/SDL.h>
10+
#include <SDL2/SDL_image.h>
1011

1112
#include "program.h"
1213
#include "texture.h"
@@ -121,6 +122,53 @@ void Context::set_feature(context_feature feature, bool on) {
121122
}
122123

123124

125+
void Context::screenshot(const std::string &filename) {
126+
log::log(MSG(info) << "Saving screenshot to " << filename);
127+
128+
// surface color masks.
129+
int32_t rmask, gmask, bmask, amask;
130+
rmask = 0x000000FF;
131+
gmask = 0x0000FF00;
132+
bmask = 0x00FF0000;
133+
amask = 0xFF000000;
134+
135+
// create output surface which will be stored later.
136+
SDL_Surface *screen = SDL_CreateRGBSurface(
137+
SDL_SWSURFACE,
138+
this->canvas_size.x, this->canvas_size.y,
139+
32, rmask, gmask, bmask, amask
140+
);
141+
142+
size_t pxcount = screen->w * screen->h;
143+
144+
auto pxdata = std::make_unique<uint32_t[]>(pxcount);
145+
146+
// copy the whole framebuffer to our local buffer.
147+
glReadPixels(0, 0,
148+
this->canvas_size.x, this->canvas_size.y,
149+
GL_RGBA, GL_UNSIGNED_BYTE, pxdata.get());
150+
151+
uint32_t *surface_pxls = reinterpret_cast<uint32_t *>(screen->pixels);
152+
153+
// now copy the raw data to the sdl surface.
154+
// we need to invert all pixel rows, but leave column order the same.
155+
for (ssize_t row = 0; row < screen->h; row++) {
156+
ssize_t irow = screen->h - 1 - row;
157+
for (ssize_t col = 0; col < screen->w; col++) {
158+
uint32_t pxl = pxdata[irow * screen->w + col];
159+
160+
// TODO: store the alpha channels in the screenshot,
161+
// is buggy at the moment..
162+
surface_pxls[row * screen->w + col] = pxl | 0xFF000000;
163+
}
164+
}
165+
166+
// call sdl_image for saving the screenshot to png
167+
IMG_SavePNG(screen, filename.c_str());
168+
SDL_FreeSurface(screen);
169+
}
170+
171+
124172
std::shared_ptr<renderer::Texture> Context::register_texture(const TextureData &data) {
125173
std::shared_ptr<renderer::Texture> txt = std::make_shared<opengl::Texture>(data);
126174
return txt;
@@ -131,6 +179,11 @@ std::shared_ptr<renderer::Program> Context::register_program(const ProgramSource
131179
return txt;
132180
}
133181

182+
void Context::resize_canvas(const coord::window &new_size) {
183+
log::log(MSG(dbg) << "opengl viewport resize to " << new_size.x << "x" << new_size.y);
184+
185+
glViewport(0, 0, new_size.x, new_size.y);
186+
}
134187

135188

136189
}}} // namespace openage::renderer::opengl

0 commit comments

Comments
 (0)