1// SuperTux
2// Copyright (C) 2006 Matthias Braun <matze@braunis.de>
3// Copyright (C) 2018 Ingo Ruhnke <grumbel@gmail.com>
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18#include "video/compositor.hpp"
19
20#include "math/rect.hpp"
21#include "video/drawing_request.hpp"
22#include "video/painter.hpp"
23#include "video/renderer.hpp"
24#include "video/video_system.hpp"
25
26bool Compositor::s_render_lighting = true;
27
28Compositor::Compositor(VideoSystem& video_system) :
29 m_video_system(video_system),
30 m_obst(),
31 m_drawing_contexts()
32{
33 obstack_init(&m_obst);
34}
35
36Compositor::~Compositor()
37{
38 m_drawing_contexts.clear();
39 obstack_free(&m_obst, nullptr);
40}
41
42DrawingContext&
43Compositor::make_context(bool overlay)
44{
45 m_drawing_contexts.emplace_back(new DrawingContext(m_video_system, m_obst, overlay));
46 return *m_drawing_contexts.back();
47}
48
49void
50Compositor::render()
51{
52 auto& lightmap = m_video_system.get_lightmap();
53
54 bool use_lightmap = std::any_of(m_drawing_contexts.begin(), m_drawing_contexts.end(),
55 [](std::unique_ptr<DrawingContext>& ctx){
56 return ctx->use_lightmap();
57 });
58
59 use_lightmap = use_lightmap && s_render_lighting;
60
61 // prepare lightmap
62 if (use_lightmap)
63 {
64 lightmap.start_draw();
65 Painter& painter = lightmap.get_painter();
66
67 for (auto& ctx : m_drawing_contexts)
68 {
69 if (!ctx->is_overlay())
70 {
71 painter.set_clip_rect(ctx->get_viewport());
72 painter.clear(ctx->get_ambient_color());
73
74 ctx->light().render(lightmap, Canvas::ALL);
75
76 painter.clear_clip_rect();
77 }
78 }
79 lightmap.end_draw();
80 }
81
82 auto back_renderer = m_video_system.get_back_renderer();
83 if (back_renderer)
84 {
85 back_renderer->start_draw();
86
87 Painter& painter = back_renderer->get_painter();
88
89 for (auto& ctx : m_drawing_contexts)
90 {
91 painter.set_clip_rect(ctx->get_viewport());
92 ctx->color().render(*back_renderer, Canvas::BELOW_LIGHTMAP);
93 painter.clear_clip_rect();
94 }
95
96 back_renderer->end_draw();
97 }
98
99 // compose the screen
100 {
101 auto& renderer = m_video_system.get_renderer();
102
103 renderer.start_draw();
104 Painter& painter = renderer.get_painter();
105
106 for (auto& ctx : m_drawing_contexts)
107 {
108 painter.set_clip_rect(ctx->get_viewport());
109 ctx->color().render(renderer, Canvas::BELOW_LIGHTMAP);
110 painter.clear_clip_rect();
111 }
112
113 if (use_lightmap)
114 {
115 const TexturePtr& texture = lightmap.get_texture();
116 if (texture)
117 {
118 TextureRequest request;
119
120 request.type = TEXTURE;
121 request.flip = 0;
122 request.alpha = 1.0f;
123 request.blend = Blend::MOD;
124
125 request.srcrects.emplace_back(0, 0,
126 static_cast<float>(texture->get_image_width()),
127 static_cast<float>(texture->get_image_height()));
128 request.dstrects.emplace_back(Vector(0, 0), lightmap.get_logical_size());
129 request.angles.emplace_back(0.0f);
130
131 request.texture = texture.get();
132 request.color = Color::WHITE;
133
134 painter.draw_texture(request);
135 }
136 }
137
138 // Render overlay elements
139 for (auto& ctx : m_drawing_contexts)
140 {
141 painter.set_clip_rect(ctx->get_viewport());
142 ctx->color().render(renderer, Canvas::ABOVE_LIGHTMAP);
143 painter.clear_clip_rect();
144 }
145
146 renderer.end_draw();
147 }
148
149 // cleanup
150 for (auto& ctx : m_drawing_contexts)
151 {
152 ctx->clear();
153 }
154 m_video_system.flip();
155
156 obstack_free(&m_obst, nullptr);
157 obstack_init(&m_obst);
158}
159
160/* EOF */
161