Flutter Impeller
blit_command_gles.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
6 
7 #include "flutter/fml/closure.h"
11 
12 namespace impeller {
13 
15 
16 static void DeleteFBO(const ProcTableGLES& gl, GLuint fbo, GLenum type) {
17  if (fbo != GL_NONE) {
18  gl.BindFramebuffer(type, GL_NONE);
19  gl.DeleteFramebuffers(1u, &fbo);
20  }
21 };
22 
23 static std::optional<GLuint> ConfigureFBO(
24  const ProcTableGLES& gl,
25  const std::shared_ptr<Texture>& texture,
26  GLenum fbo_type) {
27  auto handle = TextureGLES::Cast(texture.get())->GetGLHandle();
28  if (!handle.has_value()) {
29  return std::nullopt;
30  }
31 
32  if (TextureGLES::Cast(*texture).IsWrapped()) {
33  // The texture is attached to the default FBO, so there's no need to
34  // create/configure one.
35  gl.BindFramebuffer(fbo_type, 0);
36  return 0;
37  }
38 
39  GLuint fbo;
40  gl.GenFramebuffers(1u, &fbo);
41  gl.BindFramebuffer(fbo_type, fbo);
42 
45  VALIDATION_LOG << "Could not attach texture to framebuffer.";
46  DeleteFBO(gl, fbo, fbo_type);
47  return std::nullopt;
48  }
49 
50  if (gl.CheckFramebufferStatus(fbo_type) != GL_FRAMEBUFFER_COMPLETE) {
51  VALIDATION_LOG << "Could not create a complete framebuffer.";
52  DeleteFBO(gl, fbo, fbo_type);
53  return std::nullopt;
54  }
55 
56  return fbo;
57 };
58 
60  default;
61 
63  return label;
64 }
65 
67  const ReactorGLES& reactor) const {
68  const auto& gl = reactor.GetProcTable();
69 
70  // glBlitFramebuffer is a GLES3 proc. Since we target GLES2, we need to
71  // emulate the blit when it's not available in the driver.
72  if (!gl.BlitFramebuffer.IsAvailable()) {
73  // TODO(bdero): Emulate the blit using a raster draw call here.
74  FML_LOG(ERROR) << "Texture blit fallback not implemented yet for GLES2.";
75  return false;
76  }
77 
78  GLuint read_fbo = GL_NONE;
79  GLuint draw_fbo = GL_NONE;
80  fml::ScopedCleanupClosure delete_fbos([&gl, &read_fbo, &draw_fbo]() {
81  DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER);
82  DeleteFBO(gl, draw_fbo, GL_DRAW_FRAMEBUFFER);
83  });
84 
85  {
86  auto read = ConfigureFBO(gl, source, GL_READ_FRAMEBUFFER);
87  if (!read.has_value()) {
88  return false;
89  }
90  read_fbo = read.value();
91  }
92 
93  {
94  auto draw = ConfigureFBO(gl, destination, GL_DRAW_FRAMEBUFFER);
95  if (!draw.has_value()) {
96  return false;
97  }
98  draw_fbo = draw.value();
99  }
100 
101  gl.Disable(GL_SCISSOR_TEST);
102  gl.Disable(GL_DEPTH_TEST);
103  gl.Disable(GL_STENCIL_TEST);
104 
105  gl.BlitFramebuffer(source_region.GetX(), // srcX0
106  source_region.GetY(), // srcY0
107  source_region.GetWidth(), // srcX1
108  source_region.GetHeight(), // srcY1
109  destination_origin.x, // dstX0
110  destination_origin.y, // dstY0
111  source_region.GetWidth(), // dstX1
112  source_region.GetHeight(), // dstY1
113  GL_COLOR_BUFFER_BIT, // mask
114  GL_NEAREST // filter
115  );
116 
117  return true;
118 };
119 
121  default;
122 
124  return label;
125 }
126 
128  const ReactorGLES& reactor) const {
129  if (source->GetTextureDescriptor().format != PixelFormat::kR8G8B8A8UNormInt) {
130  VALIDATION_LOG << "Only textures with pixel format RGBA are supported yet.";
131  return false;
132  }
133 
134  const auto& gl = reactor.GetProcTable();
135 
136  GLuint read_fbo = GL_NONE;
137  fml::ScopedCleanupClosure delete_fbos(
138  [&gl, &read_fbo]() { DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER); });
139 
140  {
141  auto read = ConfigureFBO(gl, source, GL_READ_FRAMEBUFFER);
142  if (!read.has_value()) {
143  return false;
144  }
145  read_fbo = read.value();
146  }
147 
149  .UpdateBufferData([&gl, this](uint8_t* data, size_t length) {
150  gl.ReadPixels(source_region.GetX(), source_region.GetY(),
152  GL_RGBA, GL_UNSIGNED_BYTE, data + destination_offset);
153  });
154 
155  return true;
156 };
157 
159 
161  return label;
162 }
163 
165  auto texture_gles = TextureGLES::Cast(texture.get());
166  if (!texture_gles->GenerateMipmap()) {
167  return false;
168  }
169 
170  return true;
171 };
172 
173 } // namespace impeller
impeller::ReactorGLES::GetProcTable
const ProcTableGLES & GetProcTable() const
Get the OpenGL proc. table the reactor uses to manage handles.
Definition: reactor_gles.cc:48
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::BlitCopyTextureToTextureCommandGLES::Encode
bool Encode(const ReactorGLES &reactor) const override
Definition: blit_command_gles.cc:66
impeller::DeleteFBO
static void DeleteFBO(const ProcTableGLES &gl, GLuint fbo, GLenum type)
Definition: blit_command_gles.cc:16
impeller::ConfigureFBO
static std::optional< GLuint > ConfigureFBO(const ProcTableGLES &gl, const std::shared_ptr< Texture > &texture, GLenum fbo_type)
Definition: blit_command_gles.cc:23
impeller::PixelFormat::kR8G8B8A8UNormInt
@ kR8G8B8A8UNormInt
impeller::BlitCopyTextureToTextureCommand::destination
std::shared_ptr< Texture > destination
Definition: blit_command.h:20
impeller::TextureGLES::GetGLHandle
std::optional< GLuint > GetGLHandle() const
Definition: texture_gles.cc:418
texture_gles.h
impeller::TRect::GetX
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
Definition: rect.h:300
impeller::TRect::GetHeight
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
Definition: rect.h:314
impeller::TextureGLES::AttachmentType::kColor0
@ kColor0
validation.h
impeller::BlitCopyTextureToTextureCommand::destination_origin
IPoint destination_origin
Definition: blit_command.h:22
impeller::BlitCopyTextureToTextureCommandGLES::~BlitCopyTextureToTextureCommandGLES
~BlitCopyTextureToTextureCommandGLES() override
impeller::BlitGenerateMipmapCommand::texture
std::shared_ptr< Texture > texture
Definition: blit_command.h:39
device_buffer_gles.h
impeller::BlitCommand::label
std::string label
Definition: blit_command.h:15
impeller::BlitGenerateMipmapCommandGLES::Encode
bool Encode(const ReactorGLES &reactor) const override
Definition: blit_command_gles.cc:164
impeller::TRect::GetWidth
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
Definition: rect.h:308
impeller::BlitCopyTextureToBufferCommand::destination_offset
size_t destination_offset
Definition: blit_command.h:29
impeller::BlitCopyTextureToBufferCommand::destination
std::shared_ptr< DeviceBuffer > destination
Definition: blit_command.h:27
impeller::BlitCopyTextureToBufferCommandGLES::GetLabel
std::string GetLabel() const override
Definition: blit_command_gles.cc:123
impeller::ProcTableGLES
Definition: proc_table_gles.h:229
impeller::BlitCopyTextureToTextureCommand::source
std::shared_ptr< Texture > source
Definition: blit_command.h:19
impeller::BlitCopyTextureToBufferCommandGLES::Encode
bool Encode(const ReactorGLES &reactor) const override
Definition: blit_command_gles.cc:127
impeller::DeviceBufferGLES::UpdateBufferData
void UpdateBufferData(const std::function< void(uint8_t *, size_t length)> &update_buffer_data)
Definition: device_buffer_gles.cc:117
impeller::TPoint::x
Type x
Definition: point.h:30
blit_command_gles.h
impeller::BlitGenerateMipmapCommandGLES::GetLabel
std::string GetLabel() const override
Definition: blit_command_gles.cc:160
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:73
impeller::BlitCopyTextureToBufferCommandGLES::~BlitCopyTextureToBufferCommandGLES
~BlitCopyTextureToBufferCommandGLES() override
impeller::BackendCast< TextureGLES, Texture >::Cast
static TextureGLES & Cast(Texture &base)
Definition: backend_cast.h:13
impeller::BlitCopyTextureToBufferCommand::source
std::shared_ptr< Texture > source
Definition: blit_command.h:26
impeller::BlitCopyTextureToTextureCommand::source_region
IRect source_region
Definition: blit_command.h:21
impeller::ReactorGLES
The reactor attempts to make thread-safe usage of OpenGL ES easier to reason about.
Definition: reactor_gles.h:56
impeller::TextureGLES::IsWrapped
IsWrapped
Definition: texture_gles.h:25
impeller::BlitGenerateMipmapCommandGLES::~BlitGenerateMipmapCommandGLES
~BlitGenerateMipmapCommandGLES() override
impeller::BlitCopyTextureToTextureCommandGLES::GetLabel
std::string GetLabel() const override
Definition: blit_command_gles.cc:62
impeller::TRect::GetY
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
Definition: rect.h:304
impeller
Definition: aiks_blur_unittests.cc:20
impeller::BlitCopyTextureToBufferCommand::source_region
IRect source_region
Definition: blit_command.h:28
impeller::TextureGLES::SetAsFramebufferAttachment
bool SetAsFramebufferAttachment(GLenum target, AttachmentType attachment_type) const
Definition: texture_gles.cc:499
impeller::BlitEncodeGLES::~BlitEncodeGLES
virtual ~BlitEncodeGLES()