2
* Copyright © 2013 Canonical Ltd.
4
* This program is free software: you can redistribute it and/or modify it
5
* under the terms of the GNU General Public License version 3,
6
* as published by the Free Software Foundation.
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16
* Authored by: Alexandros Frantzis <alexandros.frantzis@canonical.com>
19
#include "display_buffer.h"
20
#include "mir/graphics/gl_extensions_base.h"
23
#include <boost/throw_exception.hpp>
26
#include MIR_SERVER_GL_H
27
#include MIR_SERVER_GLEXT_H
29
namespace mg = mir::graphics;
30
namespace mgo = mg::offscreen;
31
namespace geom = mir::geometry;
36
class GLExtensions : public mg::GLExtensionsBase
41
reinterpret_cast<char const*>(glGetString(GL_EXTENSIONS))}
48
mgo::detail::GLFramebufferObject::GLFramebufferObject(geom::Size const& size)
49
: size{size}, color_renderbuffer{0}, depth_renderbuffer{0}, fbo{0}
51
/* Save previous FBO state */
52
glGetIntegerv(GL_FRAMEBUFFER_BINDING, &old_fbo);
53
glGetIntegerv(GL_VIEWPORT, old_viewport);
55
GLExtensions const extensions;
57
GLenum gl_color_format{GL_RGBA4};
58
GLenum const gl_depth_format{GL_DEPTH_COMPONENT16};
61
if (extensions.support("GL_ARM_rgba8") ||
62
extensions.support("GL_OES_rgb8_rgba8"))
64
gl_color_format = GL_RGBA8_OES;
68
/* Create a renderbuffer for the color attachment */
69
glGenRenderbuffers(1, &color_renderbuffer);
70
glBindRenderbuffer(GL_RENDERBUFFER, color_renderbuffer);
71
glRenderbufferStorage(GL_RENDERBUFFER, gl_color_format,
72
size.width.as_int(), size.height.as_int());
74
/* Create a renderbuffer for the depth attachment */
75
glGenRenderbuffers(1, &depth_renderbuffer);
76
glBindRenderbuffer(GL_RENDERBUFFER, depth_renderbuffer);
77
glRenderbufferStorage(GL_RENDERBUFFER, gl_depth_format,
78
size.width.as_int(), size.height.as_int());
80
/* Create a FBO and set it up */
81
glGenFramebuffers(1, &fbo);
83
auto const fbo_raii = mir::raii::paired_calls(
84
[this] { glBindFramebuffer(GL_FRAMEBUFFER, fbo); },
85
[this] { glBindFramebuffer(GL_FRAMEBUFFER, old_fbo); });
87
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
88
GL_RENDERBUFFER, color_renderbuffer);
89
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
90
GL_RENDERBUFFER, depth_renderbuffer);
92
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
93
BOOST_THROW_EXCEPTION(std::runtime_error("Failed to set up FBO"));
96
mgo::detail::GLFramebufferObject::~GLFramebufferObject()
99
glDeleteFramebuffers(1, &fbo);
100
if (color_renderbuffer)
101
glDeleteRenderbuffers(1, &color_renderbuffer);
102
if (depth_renderbuffer)
103
glDeleteRenderbuffers(1, &depth_renderbuffer);
106
void mgo::detail::GLFramebufferObject::bind() const
108
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
109
glViewport(0, 0, size.width.as_int(), size.height.as_int());
112
void mgo::detail::GLFramebufferObject::unbind() const
114
glBindFramebuffer(GL_FRAMEBUFFER, old_fbo);
115
glViewport(old_viewport[0], old_viewport[1],
116
old_viewport[2], old_viewport[3]);
119
mgo::DisplayBuffer::DisplayBuffer(SurfacelessEGLContext egl_context,
120
geom::Rectangle const& area)
121
: egl_context{std::move(egl_context)},
127
geom::Rectangle mgo::DisplayBuffer::view_area() const
132
void mgo::DisplayBuffer::make_current()
134
egl_context.make_current();
137
void mgo::DisplayBuffer::bind()
142
void mgo::DisplayBuffer::release_current()
145
egl_context.release_current();
148
void mgo::DisplayBuffer::swap_buffers()
153
bool mgo::DisplayBuffer::overlay(RenderableList const&)
158
glm::mat2 mgo::DisplayBuffer::transformation() const
163
mg::NativeDisplayBuffer* mgo::DisplayBuffer::native_display_buffer()