Skip to content

Commit

Permalink
Use GLES3 blit if available
Browse files Browse the repository at this point in the history
  • Loading branch information
bdero committed Jul 26, 2022
1 parent e3c875f commit 6e6d4ab
Show file tree
Hide file tree
Showing 8 changed files with 105 additions and 12 deletions.
2 changes: 1 addition & 1 deletion impeller/renderer/backend/gles/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ impeller_component("gles") {
if (!is_android && !is_fuchsia) {
public_configs = [ ":gles_config" ]
sources += [
"//third_party/angle/include/GLES2/gl2.h",
"//third_party/angle/include/GLES2/gl2ext.h",
"//third_party/angle/include/GLES3/gl3.h",
]
}

Expand Down
91 changes: 88 additions & 3 deletions impeller/renderer/backend/gles/blit_pass_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@

#include <algorithm>

#include "GLES2/gl2.h"
#include "flutter/fml/trace_event.h"
#include "impeller/base/config.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/gles/device_buffer_gles.h"
#include "impeller/renderer/backend/gles/formats_gles.h"
#include "impeller/renderer/backend/gles/pipeline_gles.h"
#include "impeller/renderer/backend/gles/proc_table_gles.h"
#include "impeller/renderer/backend/gles/texture_gles.h"
#include "impeller/renderer/formats.h"

Expand All @@ -35,6 +35,56 @@ void BlitPassGLES::OnSetLabel(std::string label) {
label_ = std::move(label);
}

static void DeleteFBO(const ProcTableGLES& gl, GLuint fbo, GLenum type) {
if (fbo != GL_NONE) {
gl.BindFramebuffer(type, GL_NONE);
gl.DeleteFramebuffers(1u, &fbo);
}
};

static std::optional<GLuint> BindFBO(const ProcTableGLES& gl,
const std::shared_ptr<Texture>& texture,
GLenum type) {
auto handle = TextureGLES::Cast(texture.get())->GetGLHandle();
if (!handle.has_value()) {
return std::nullopt;
}

if (TextureGLES::Cast(*texture).IsWrapped()) {
gl.BindFramebuffer(type, 0);
return 0; // The texture is attached to the default FBO.
}

GLuint fbo;
gl.GenFramebuffers(1u, &fbo);
gl.BindFramebuffer(type, fbo);
switch (TextureGLES::Cast(*texture).GetType()) {
case TextureGLES::Type::kTexture:
gl.FramebufferTexture2D(type, // target
GL_COLOR_ATTACHMENT0, // attachment
GL_TEXTURE_2D, // textarget
handle.value(), // texture
0 // level
);
break;
case TextureGLES::Type::kRenderBuffer:
gl.FramebufferRenderbuffer(type, // target
GL_COLOR_ATTACHMENT0, // attachment
GL_RENDERBUFFER, // render-buffer target
handle.value() // render-buffer
);
break;
}

if (gl.CheckFramebufferStatus(type) != GL_FRAMEBUFFER_COMPLETE) {
VALIDATION_LOG << "Could not create a complete frambuffer.";
DeleteFBO(gl, fbo, type);
return std::nullopt;
}

return fbo;
};

[[nodiscard]] bool EncodeCommandsInReactor(
const std::shared_ptr<Allocator>& transients_allocator,
const ReactorGLES& reactor,
Expand Down Expand Up @@ -67,14 +117,49 @@ void BlitPassGLES::OnSetLabel(std::string label) {

if (auto* copy_command =
std::get_if<BlitCommand::CopyTextureToTexture>(&command.data)) {
if (!gl.BindFramebuffer.IsAvailable()) {
// glBlitFramebuffer is a GLES3 proc. Since we target GLES2, we need to
// emulate the blit when it's not available in the driver.
if (!gl.BlitFramebuffer.IsAvailable()) {
// TODO(bdero): Emulate the blit using a raster draw call here.
return true;
}

GLuint read_fbo = GL_NONE;
GLuint draw_fbo = GL_NONE;
fml::ScopedCleanupClosure delete_fbos([&gl, &read_fbo, &draw_fbo]() {
DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER);
DeleteFBO(gl, draw_fbo, GL_DRAW_FRAMEBUFFER);
});

{
auto read = BindFBO(gl, copy_command->source, GL_READ_FRAMEBUFFER);
if (!read.has_value()) {
return false;
}
read_fbo = read.value();
auto draw = BindFBO(gl, copy_command->destination, GL_DRAW_FRAMEBUFFER);
if (!draw.has_value()) {
return false;
}
read_fbo = read.value();
draw_fbo = draw.value();
}

gl.Disable(GL_SCISSOR_TEST);
gl.Disable(GL_DEPTH_TEST);
gl.Disable(GL_STENCIL_TEST);
auto source = TextureGLES::Cast(copy_command->source.get());

glBlitFramebuffer(copy_command->source_region.origin.x, // srcX0
copy_command->source_region.origin.y, // srcY0
copy_command->source_region.size.width, // srcX1
copy_command->source_region.size.height, // srcY1
copy_command->destination_origin.x, // dstX0
copy_command->destination_origin.y, // dstY0
copy_command->source_region.size.width, // dstX1
copy_command->source_region.size.height, // dstY1
GL_COLOR_BUFFER_BIT, // mask
GL_NEAREST // filter
);

}

Expand Down
1 change: 0 additions & 1 deletion impeller/renderer/backend/gles/formats_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include <optional>

#include "GLES2/gl2ext.h"
#include "flutter/fml/logging.h"
#include "flutter/fml/macros.h"
#include "impeller/renderer/backend/gles/gles.h"
Expand Down
2 changes: 1 addition & 1 deletion impeller/renderer/backend/gles/gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@

#pragma once

#include "GLES2/gl2.h"
#include "GLES3/gl3.h"
#define GL_GLEXT_PROTOTYPES
#include "GLES2/gl2ext.h"
1 change: 1 addition & 0 deletions impeller/renderer/backend/gles/proc_table_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ ProcTableGLES::ProcTableGLES(Resolver resolver) {
reinterpret_cast<decltype(proc_ivar.function)>(fn_ptr); \
proc_ivar.error_fn = error_fn; \
}
FOR_EACH_IMPELLER_GLES3_PROC(IMPELLER_PROC);
FOR_EACH_IMPELLER_EXT_PROC(IMPELLER_PROC);

#undef IMPELLER_PROC
Expand Down
4 changes: 3 additions & 1 deletion impeller/renderer/backend/gles/proc_table_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ struct GLProc {
PROC(BindTexture); \
PROC(BlendEquationSeparate); \
PROC(BlendFuncSeparate); \
PROC(BlitFramebuffer); \
PROC(BufferData); \
PROC(CheckFramebufferStatus); \
PROC(Clear); \
Expand Down Expand Up @@ -164,6 +163,8 @@ struct GLProc {
PROC(VertexAttribPointer); \
PROC(Viewport);

#define FOR_EACH_IMPELLER_GLES3_PROC(PROC) PROC(BlitFramebuffer);

#define FOR_EACH_IMPELLER_EXT_PROC(PROC) \
PROC(DiscardFramebufferEXT); \
PROC(PushDebugGroupKHR); \
Expand All @@ -190,6 +191,7 @@ class ProcTableGLES {
GLProc<decltype(gl##name)> name = {"gl" #name, nullptr};

FOR_EACH_IMPELLER_PROC(IMPELLER_PROC);
FOR_EACH_IMPELLER_GLES3_PROC(IMPELLER_PROC);
FOR_EACH_IMPELLER_EXT_PROC(IMPELLER_PROC);

#undef IMPELLER_PROC
Expand Down
14 changes: 9 additions & 5 deletions impeller/renderer/backend/gles/texture_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -350,11 +350,15 @@ void TextureGLES::InitializeContentsIfNecessary() const {
}
}

bool TextureGLES::Bind() const {
std::optional<GLuint> TextureGLES::GetGLHandle() const {
if (!IsValid()) {
return false;
return std::nullopt;
}
auto handle = reactor_->GetGLHandle(handle_);
return reactor_->GetGLHandle(handle_);
}

bool TextureGLES::Bind() const {
auto handle = GetGLHandle();
if (!handle.has_value()) {
return false;
}
Expand Down Expand Up @@ -392,7 +396,7 @@ bool TextureGLES::GenerateMipmaps() const {
return false;
}

auto handle = reactor_->GetGLHandle(handle_);
auto handle = GetGLHandle();
if (!handle.has_value()) {
return false;
}
Expand Down Expand Up @@ -423,7 +427,7 @@ bool TextureGLES::SetAsFramebufferAttachment(GLuint fbo,
return false;
}
InitializeContentsIfNecessary();
auto handle = reactor_->GetGLHandle(handle_);
auto handle = GetGLHandle();
if (!handle.has_value()) {
return false;
}
Expand Down
2 changes: 2 additions & 0 deletions impeller/renderer/backend/gles/texture_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ class TextureGLES final : public Texture,
// |Texture|
~TextureGLES() override;

std::optional<GLuint> GetGLHandle() const;

[[nodiscard]] bool Bind() const;

[[nodiscard]] bool GenerateMipmaps() const;
Expand Down

0 comments on commit 6e6d4ab

Please sign in to comment.