Skip to content

Commit

Permalink
Merge pull request #1598 from heinezen/fix/qtwayland
Browse files Browse the repository at this point in the history
Dynamically fetch default FBO
  • Loading branch information
TheJJ authored Nov 4, 2023
2 parents 441fa62 + 3885116 commit bd06a25
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 59 deletions.
4 changes: 4 additions & 0 deletions libopenage/renderer/opengl/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ std::shared_ptr<QOpenGLContext> GlContext::get_raw_context() const {
return this->gl_context;
}

GLuint GlContext::get_default_framebuffer_id() {
return this->gl_context->defaultFramebufferObject();
}

gl_context_spec GlContext::get_specs() const {
return this->specs;
}
Expand Down
11 changes: 11 additions & 0 deletions libopenage/renderer/opengl/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ class GlContext {
*/
std::shared_ptr<QOpenGLContext> get_raw_context() const;

/**
* Get the ID of the default framebuffer used for displaying to
* the window.
*
* This value may change on every frame, so it should be called every
* time the default framebuffer is bound.
*
* @return ID of the default (display) framebuffer.
*/
unsigned int get_default_framebuffer_id();

/**
* Get the capabilities of this context.
*/
Expand Down
32 changes: 29 additions & 3 deletions libopenage/renderer/opengl/framebuffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,25 @@

#include "framebuffer.h"

#include "renderer/opengl/context.h"
#include "renderer/opengl/texture.h"


namespace openage::renderer::opengl {

GlFramebuffer::GlFramebuffer(const std::shared_ptr<GlContext> &context) :
GlSimpleObject(context,
[](GLuint /*handle*/) {}),
type{gl_framebuffer_t::display} {
}

// TODO the validity of this object is contingent
// on its texture existing. use shared_ptr?
GlFramebuffer::GlFramebuffer(const std::shared_ptr<GlContext> &context,
std::vector<std::shared_ptr<GlTexture2d>> const &textures) :
GlSimpleObject(context,
[](GLuint handle) { glDeleteFramebuffers(1, &handle); }) {
[](GLuint handle) { glDeleteFramebuffers(1, &handle); }),
type{gl_framebuffer_t::textures} {
GLuint handle;
glGenFramebuffers(1, &handle);
this->handle = handle;
Expand All @@ -21,6 +29,10 @@ GlFramebuffer::GlFramebuffer(const std::shared_ptr<GlContext> &context,

std::vector<GLenum> drawBuffers;

if (textures.empty()) {
throw Error{ERR << "At least 1 texture must be assigned to texture framebuffer."};
}

size_t colorTextureCount = 0;
for (auto const &texture : textures) {
// TODO figure out attachment points from pixel formats
Expand All @@ -41,12 +53,26 @@ GlFramebuffer::GlFramebuffer(const std::shared_ptr<GlContext> &context,
}
}

gl_framebuffer_t GlFramebuffer::get_type() const {
return this->type;
}

void GlFramebuffer::bind_read() const {
glBindFramebuffer(GL_READ_FRAMEBUFFER, *this->handle);
if (this->type == gl_framebuffer_t::textures) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, *this->handle);
}
else {
glBindFramebuffer(GL_READ_FRAMEBUFFER, this->context->get_default_framebuffer_id());
}
}

void GlFramebuffer::bind_write() const {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *this->handle);
if (this->type == gl_framebuffer_t::textures) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, *this->handle);
}
else {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, this->context->get_default_framebuffer_id());
}
}

} // namespace openage::renderer::opengl
73 changes: 59 additions & 14 deletions libopenage/renderer/opengl/framebuffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,30 +7,75 @@
#include "renderer/opengl/simple_object.h"


namespace openage {
namespace renderer {
namespace opengl {
namespace openage::renderer::opengl {

class GlTexture2d;

/// Represents an OpenGL Framebuffer Object.
/// It is a collection of bitmap targets that can be drawn into
/// and read from.
/**
* The type of OpenGL framebuffer.
*/
enum class gl_framebuffer_t {
/**
* The actual window. This is visible to the user after swapping front and back buffers.
*/
display,
/**
* A bunch of textures. These can be color texture, depth textures, etc.
*/
textures,
};

/**
* Represents an OpenGL Framebuffer Object.
* It is a collection of bitmap targets that can be drawn into
* and read from.
*/
class GlFramebuffer final : public GlSimpleObject {
public:
/// Construct a framebuffer pointing at the given textures.
/// Texture are attached to points specific to their pixel format,
/// e.g. a depth texture will be set as the depth target.
/**
* Construct a framebuffer pointing at the default framebuffer - the window.
*
* Drawing into this framebuffer draws onto the screen.
*
* @param context OpenGL context used for drawing.
*/
GlFramebuffer(const std::shared_ptr<GlContext> &context);

/**
* Construct a framebuffer pointing at the given textures.
*
* Texture are attached to points specific to their pixel format,
* e.g. a depth texture will be set as the depth target.
*
* @param context OpenGL context used for drawing.
* @param textures Textures targeted by the framebuffer. They are automatically
* attached to the correct attachement points depending on their type.
*/
GlFramebuffer(const std::shared_ptr<GlContext> &context,
std::vector<std::shared_ptr<GlTexture2d>> const &textures);

/// Bind this framebuffer to GL_READ_FRAMEBUFFER.
/**
* Get the type of this framebuffer.
*
* @return Framebuffer type.
*/
gl_framebuffer_t get_type() const;

/**
* Bind this framebuffer to \p GL_READ_FRAMEBUFFER.
*/
void bind_read() const;

/// Bind this framebuffer to GL_DRAW_FRAMEBUFFER.
/**
* Bind this framebuffer to \p GL_DRAW_FRAMEBUFFER.
*/
void bind_write() const;

private:
/**
* Type of this framebuffer.
*/
gl_framebuffer_t type;
};

} // namespace opengl
} // namespace renderer
} // namespace openage
} // namespace openage::renderer::opengl
34 changes: 13 additions & 21 deletions libopenage/renderer/opengl/render_target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,20 @@

#include "render_target.h"

#include "error/error.h"

#include "renderer/opengl/texture.h"

namespace openage::renderer::opengl {

GlRenderTarget::GlRenderTarget(size_t width, size_t height) :
type(gl_render_target_t::display),
size(width, height) {}
GlRenderTarget::GlRenderTarget(const std::shared_ptr<GlContext> &context, size_t width, size_t height) :
type(gl_render_target_t::framebuffer),
size(width, height),
framebuffer(context) {}

GlRenderTarget::GlRenderTarget(const std::shared_ptr<GlContext> &context,
const std::vector<std::shared_ptr<GlTexture2d>> &textures) :
type(gl_render_target_t::textures),
type(gl_render_target_t::framebuffer),
framebuffer({context, textures}),
textures(textures) {
// TODO: Check if the textures are all the same size
Expand All @@ -21,7 +24,7 @@ GlRenderTarget::GlRenderTarget(const std::shared_ptr<GlContext> &context,

std::vector<std::shared_ptr<Texture2d>> GlRenderTarget::get_texture_targets() {
std::vector<std::shared_ptr<Texture2d>> textures{};
if (this->type == gl_render_target_t::display) {
if (this->framebuffer->get_type() == gl_framebuffer_t::display) {
return textures;
}
//else upcast pointers
Expand All @@ -33,8 +36,9 @@ std::vector<std::shared_ptr<Texture2d>> GlRenderTarget::get_texture_targets() {
}

void GlRenderTarget::resize(size_t width, size_t height) {
if (this->type != gl_render_target_t::display) {
throw Error{ERR << "Texture render target should not be resized. Create a new one instead."};
if (this->framebuffer->get_type() == gl_framebuffer_t::textures) {
throw Error{ERR << "Render target with textured framebuffer should not be resized. "
<< "Create a new one instead."};
}

this->size = std::make_pair(width, height);
Expand All @@ -46,23 +50,11 @@ void GlRenderTarget::bind_write() const {
// different sizes
glViewport(0, 0, size.first, size.second);

if (this->type == gl_render_target_t::textures) {
this->framebuffer->bind_write();
}
else {
// 0 is the default, window framebuffer
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
}
this->framebuffer->bind_write();
}

void GlRenderTarget::bind_read() const {
if (this->type == gl_render_target_t::textures) {
this->framebuffer->bind_read();
}
else {
// 0 is the default, window framebuffer
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
}
this->framebuffer->bind_read();
}

} // namespace openage::renderer::opengl
82 changes: 62 additions & 20 deletions libopenage/renderer/opengl/render_target.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,50 +17,92 @@ namespace opengl {

class GlTexture2d;

/// The type of OpenGL render target
/**
* The type of OpenGL render target.
*/
enum class gl_render_target_t {
/// The actual window. This is visible to the user after swapping front and back buffers
display,
/// A bunch of textures
textures,
/**
* Render into a framebuffer.
*/
framebuffer,
// TODO renderbuffers mixed with textures
};

/// Represents an OpenGL target that can be drawn into.
/// It can be either a framebuffer or the display (the window).
/**
* Represents an OpenGL target that can be drawn into.
* It can be either a framebuffer with texture attachements or the display (the window).
*/
class GlRenderTarget final : public RenderTarget {
public:
/// Construct a render target pointed at the default framebuffer - the window.
GlRenderTarget(size_t width, size_t height);

/// Construct a render target pointing at the given textures.
/// Texture are attached to points specific to their pixel format,
/// e.g. a depth texture will be set as the depth target.
/**
* Construct a render target pointed at the default framebuffer - the window.
*
* @param context OpenGL context used for drawing.
* @param width Current width of the window.
* @param height Current height of the window.
*/
GlRenderTarget(const std::shared_ptr<GlContext> &context,
size_t width,
size_t height);

/**
* Construct a render target pointing at the given textures.
* Texture are attached to points specific to their pixel format,
* e.g. a depth texture will be set as the depth target.
*
* @param context OpenGL context used for drawing.
* @param textures Texture attachements.
*/
GlRenderTarget(const std::shared_ptr<GlContext> &context,
std::vector<std::shared_ptr<GlTexture2d>> const &textures);

// Get the targeted textures
/**
* Get the targeted textures.
*
* @return Textures drawn into by the render target.
*/
std::vector<std::shared_ptr<Texture2d>> get_texture_targets() override;

// Resize the render target for scaling viewport correctly.
/**
* Resize the render target to the specified dimensions.
*
* This is used to scale the viewport to the correct size when
* binding the render target with write access.
*
* @param width New width.
* @param height New height.
*/
void resize(size_t width, size_t height);

/// Bind this render target to be drawn into.
/**
* Bind this render target to be drawn into.
*/
void bind_write() const;

/// Bind this render target to be read from.
/**
* Bind this render target to be read from.
*/
void bind_read() const;

private:
/**
* Type of this render target.
*/
gl_render_target_t type;

// Size of the window or the texture target
/**
* Size of the window or the texture targets.
*/
std::pair<size_t, size_t> size;

/// For textures target type, the framebuffer.
/**
* For framebuffer target type, the framebuffer.
*/
std::optional<GlFramebuffer> framebuffer;

// target textures if the render target is an fbo
/**
* Target textures if the render target is a textured fbo.
*/
std::optional<std::vector<std::shared_ptr<GlTexture2d>>> textures;
};

Expand Down
4 changes: 3 additions & 1 deletion libopenage/renderer/opengl/renderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ namespace openage::renderer::opengl {
GlRenderer::GlRenderer(const std::shared_ptr<GlContext> &ctx,
const util::Vector2s &viewport_size) :
gl_context{ctx},
display{std::make_shared<GlRenderTarget>(viewport_size[0], viewport_size[1])} {
display{std::make_shared<GlRenderTarget>(ctx,
viewport_size[0],
viewport_size[1])} {
// global GL alpha blending settings
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

Expand Down

0 comments on commit bd06a25

Please sign in to comment.