7 #include "flutter/fml/closure.h"
19 static void FlipImage(uint8_t* buffer,
23 if (buffer ==
nullptr || stride == 0) {
27 const auto byte_width = width * stride;
29 for (
size_t top = 0; top < height; top++) {
30 size_t bottom = height - top - 1;
34 auto* top_row = buffer + byte_width * top;
35 auto* bottom_row = buffer + byte_width * bottom;
36 std::swap_ranges(top_row, top_row + byte_width, bottom_row);
45 gl.BindFramebuffer(
type, GL_NONE);
46 gl.DeleteFramebuffers(1u, &fbo);
52 const std::shared_ptr<Texture>& texture,
55 if (!handle.has_value()) {
62 gl.BindFramebuffer(fbo_type, 0);
67 gl.GenFramebuffers(1u, &fbo);
68 gl.BindFramebuffer(fbo_type, fbo);
77 GLenum status = gl.CheckFramebufferStatus(fbo_type);
78 if (status != GL_FRAMEBUFFER_COMPLETE) {
101 if (!gl.BlitFramebuffer.IsAvailable()) {
103 VALIDATION_LOG <<
"Texture blit fallback not implemented yet for GLES2.";
107 GLuint read_fbo = GL_NONE;
108 GLuint draw_fbo = GL_NONE;
109 fml::ScopedCleanupClosure delete_fbos([&gl, &read_fbo, &draw_fbo]() {
110 DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER);
111 DeleteFBO(gl, draw_fbo, GL_DRAW_FRAMEBUFFER);
116 if (!read.has_value()) {
119 read_fbo = read.value();
124 if (!draw.has_value()) {
127 draw_fbo = draw.value();
130 gl.Disable(GL_SCISSOR_TEST);
131 gl.Disable(GL_DEPTH_TEST);
132 gl.Disable(GL_STENCIL_TEST);
150 struct TexImage2DData {
156 explicit TexImage2DData(
PixelFormat pixel_format) {
157 switch (pixel_format) {
161 type = GL_UNSIGNED_BYTE;
166 type = GL_UNSIGNED_BYTE;
174 type = GL_UNSIGNED_BYTE;
189 type = GL_HALF_FLOAT;
200 type = GL_UNSIGNED_INT_24_8;
213 TexImage2DData(
PixelFormat pixel_format, BufferView p_buffer_view)
214 : TexImage2DData(pixel_format) {
218 bool IsValid()
const {
return is_valid_; }
221 bool is_valid_ =
false;
237 VALIDATION_LOG <<
"Incorrect texture usage flags for setting contents on "
238 "this texture object.";
243 VALIDATION_LOG <<
"Cannot set the contents of a wrapped texture.";
249 if (tex_descriptor.size.IsEmpty()) {
253 if (!tex_descriptor.IsValid() ||
263 GLenum texture_target;
264 switch (tex_descriptor.type) {
266 texture_type = GL_TEXTURE_2D;
267 texture_target = GL_TEXTURE_2D;
270 VALIDATION_LOG <<
"Multisample texture uploading is not supported for "
271 "the OpenGLES backend.";
274 texture_type = GL_TEXTURE_CUBE_MAP;
275 texture_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X +
slice;
278 texture_type = GL_TEXTURE_EXTERNAL_OES;
279 texture_target = GL_TEXTURE_EXTERNAL_OES;
283 TexImage2DData
data = TexImage2DData(tex_descriptor.format,
source);
284 if (!
data.IsValid()) {
290 if (!gl_handle.has_value()) {
292 <<
"Texture was collected before it could be uploaded to the GPU.";
296 gl.BindTexture(texture_type, gl_handle.value());
297 const GLvoid* tex_data =
data.buffer_view.GetBuffer()->OnGetContents() +
298 data.buffer_view.GetRange().offset;
303 gl.TexImage2D(texture_target,
305 data.internal_format,
306 tex_descriptor.size.width,
307 tex_descriptor.size.height,
309 data.external_format,
317 gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
318 gl.TexSubImage2D(texture_target,
324 data.external_format,
343 VALIDATION_LOG <<
"Only textures with pixel format RGBA are supported yet.";
350 GLuint read_fbo = GL_NONE;
351 fml::ScopedCleanupClosure delete_fbos(
352 [&gl, &read_fbo]() {
DeleteFBO(gl, read_fbo, GL_FRAMEBUFFER); });
356 if (!read.has_value()) {
359 read_fbo = read.value();
364 rows =
source->GetSize().height](uint8_t*
data,
367 gl.ReadPixels(source_region.GetX(), source_region.GetY(),
368 source_region.GetWidth(), source_region.GetHeight(),
369 GL_RGBA, GL_UNSIGNED_BYTE, data + destination_offset);
370 switch (coord_system) {
371 case TextureCoordinateSystem::kUploadFromHost:
373 case TextureCoordinateSystem::kRenderToTexture:
376 FlipImage(data + destination_offset, source_region.GetWidth(),
377 source_region.GetHeight(), 4);
384 BlitGenerateMipmapCommandGLES::~BlitGenerateMipmapCommandGLES() =
default;
386 std::string BlitGenerateMipmapCommandGLES::GetLabel()
const {
390 bool BlitGenerateMipmapCommandGLES::Encode(
const ReactorGLES& reactor)
const {
391 auto texture_gles = TextureGLES::Cast(texture.get());
392 if (!texture_gles->GenerateMipmap()) {
402 BlitResizeTextureCommandGLES::~BlitResizeTextureCommandGLES() =
default;
404 std::string BlitResizeTextureCommandGLES::GetLabel()
const {
405 return "Resize Texture";
408 bool BlitResizeTextureCommandGLES::Encode(
const ReactorGLES& reactor)
const {
413 if (!gl.BlitFramebuffer.IsAvailable()) {
415 VALIDATION_LOG <<
"Texture blit fallback not implemented yet for GLES2.";
419 destination->SetCoordinateSystem(source->GetCoordinateSystem());
421 GLuint read_fbo = GL_NONE;
422 GLuint draw_fbo = GL_NONE;
423 fml::ScopedCleanupClosure delete_fbos([&gl, &read_fbo, &draw_fbo]() {
424 DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER);
425 DeleteFBO(gl, draw_fbo, GL_DRAW_FRAMEBUFFER);
429 auto read =
ConfigureFBO(gl, source, GL_READ_FRAMEBUFFER);
430 if (!read.has_value()) {
433 read_fbo = read.value();
437 auto draw =
ConfigureFBO(gl, destination, GL_DRAW_FRAMEBUFFER);
438 if (!draw.has_value()) {
441 draw_fbo = draw.value();
444 gl.Disable(GL_SCISSOR_TEST);
445 gl.Disable(GL_DEPTH_TEST);
446 gl.Disable(GL_STENCIL_TEST);
448 const IRect source_region = IRect::MakeSize(source->GetSize());
449 const IRect destination_region = IRect::MakeSize(destination->GetSize());
451 gl.BlitFramebuffer(source_region.
GetX(),
452 source_region.
GetY(),
455 destination_region.
GetX(),
456 destination_region.
GetY(),
static TextureGLES & Cast(Texture &base)
void UpdateBufferData(const std::function< void(uint8_t *, size_t length)> &update_buffer_data)
The reactor attempts to make thread-safe usage of OpenGL ES easier to reason about.
const ProcTableGLES & GetProcTable() const
Get the OpenGL proc. table the reactor uses to manage handles.
bool IsSliceInitialized(size_t slice) const
bool SetAsFramebufferAttachment(GLenum target, AttachmentType attachment_type) const
void MarkSliceInitialized(size_t slice) const
Indicates that a specific texture slice has been initialized.
std::optional< GLuint > GetGLHandle() const
const TextureDescriptor & GetTextureDescriptor() const
constexpr size_t BytesPerPixelForPixelFormat(PixelFormat format)
static std::optional< GLuint > ConfigureFBO(const ProcTableGLES &gl, const std::shared_ptr< Texture > &texture, GLenum fbo_type)
std::string DebugToFramebufferError(int status)
PixelFormat
The Pixel formats supported by Impeller. The naming convention denotes the usage of the component,...
static void DeleteFBO(const ProcTableGLES &gl, GLuint fbo, GLenum type)
~BlitCopyBufferToTextureCommandGLES() override
std::string GetLabel() const override
bool Encode(const ReactorGLES &reactor) const override
std::shared_ptr< Texture > destination
~BlitCopyTextureToBufferCommandGLES() override
bool Encode(const ReactorGLES &reactor) const override
std::string GetLabel() const override
std::shared_ptr< DeviceBuffer > destination
std::shared_ptr< Texture > source
bool Encode(const ReactorGLES &reactor) const override
std::string GetLabel() const override
~BlitCopyTextureToTextureCommandGLES() override
IPoint destination_origin
std::shared_ptr< Texture > destination
std::shared_ptr< Texture > source
virtual ~BlitEncodeGLES()
constexpr Type GetY() const
Returns the Y coordinate of the upper left corner, equivalent to |GetOrigin().y|.
constexpr Type GetHeight() const
Returns the height of the rectangle, equivalent to |GetSize().height|.
constexpr T Area() const
Get the area of the rectangle, equivalent to |GetSize().Area()|.
constexpr Type GetX() const
Returns the X coordinate of the upper left corner, equivalent to |GetOrigin().x|.
constexpr Type GetWidth() const
Returns the width of the rectangle, equivalent to |GetSize().width|.
std::shared_ptr< const fml::Mapping > data