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;
184 type = GL_HALF_FLOAT;
195 type = GL_UNSIGNED_INT_24_8;
208 TexImage2DData(
PixelFormat pixel_format, BufferView p_buffer_view)
209 : TexImage2DData(pixel_format) {
213 bool IsValid()
const {
return is_valid_; }
216 bool is_valid_ =
false;
232 VALIDATION_LOG <<
"Incorrect texture usage flags for setting contents on "
233 "this texture object.";
238 VALIDATION_LOG <<
"Cannot set the contents of a wrapped texture.";
244 if (tex_descriptor.size.IsEmpty()) {
248 if (!tex_descriptor.IsValid() ||
258 GLenum texture_target;
259 switch (tex_descriptor.type) {
261 texture_type = GL_TEXTURE_2D;
262 texture_target = GL_TEXTURE_2D;
265 VALIDATION_LOG <<
"Multisample texture uploading is not supported for "
266 "the OpenGLES backend.";
269 texture_type = GL_TEXTURE_CUBE_MAP;
270 texture_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X +
slice;
273 texture_type = GL_TEXTURE_EXTERNAL_OES;
274 texture_target = GL_TEXTURE_EXTERNAL_OES;
278 TexImage2DData
data = TexImage2DData(tex_descriptor.format,
source);
279 if (!
data.IsValid()) {
285 if (!gl_handle.has_value()) {
287 <<
"Texture was collected before it could be uploaded to the GPU.";
291 gl.BindTexture(texture_type, gl_handle.value());
292 const GLvoid* tex_data =
data.buffer_view.GetBuffer()->OnGetContents() +
293 data.buffer_view.GetRange().offset;
298 gl.TexImage2D(texture_target,
300 data.internal_format,
301 tex_descriptor.size.width,
302 tex_descriptor.size.height,
304 data.external_format,
312 gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
313 gl.TexSubImage2D(texture_target,
319 data.external_format,
338 VALIDATION_LOG <<
"Only textures with pixel format RGBA are supported yet.";
345 GLuint read_fbo = GL_NONE;
346 fml::ScopedCleanupClosure delete_fbos(
347 [&gl, &read_fbo]() {
DeleteFBO(gl, read_fbo, GL_FRAMEBUFFER); });
351 if (!read.has_value()) {
354 read_fbo = read.value();
359 rows =
source->GetSize().height](uint8_t*
data,
362 gl.ReadPixels(source_region.GetX(), source_region.GetY(),
363 source_region.GetWidth(), source_region.GetHeight(),
364 GL_RGBA, GL_UNSIGNED_BYTE, data + destination_offset);
365 switch (coord_system) {
366 case TextureCoordinateSystem::kUploadFromHost:
368 case TextureCoordinateSystem::kRenderToTexture:
371 FlipImage(data + destination_offset, source_region.GetWidth(),
372 source_region.GetHeight(), 4);
379 BlitGenerateMipmapCommandGLES::~BlitGenerateMipmapCommandGLES() =
default;
381 std::string BlitGenerateMipmapCommandGLES::GetLabel()
const {
385 bool BlitGenerateMipmapCommandGLES::Encode(
const ReactorGLES& reactor)
const {
386 auto texture_gles = TextureGLES::Cast(texture.get());
387 if (!texture_gles->GenerateMipmap()) {
397 BlitResizeTextureCommandGLES::~BlitResizeTextureCommandGLES() =
default;
399 std::string BlitResizeTextureCommandGLES::GetLabel()
const {
400 return "Resize Texture";
403 bool BlitResizeTextureCommandGLES::Encode(
const ReactorGLES& reactor)
const {
408 if (!gl.BlitFramebuffer.IsAvailable()) {
410 VALIDATION_LOG <<
"Texture blit fallback not implemented yet for GLES2.";
414 destination->SetCoordinateSystem(source->GetCoordinateSystem());
416 GLuint read_fbo = GL_NONE;
417 GLuint draw_fbo = GL_NONE;
418 fml::ScopedCleanupClosure delete_fbos([&gl, &read_fbo, &draw_fbo]() {
419 DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER);
420 DeleteFBO(gl, draw_fbo, GL_DRAW_FRAMEBUFFER);
424 auto read =
ConfigureFBO(gl, source, GL_READ_FRAMEBUFFER);
425 if (!read.has_value()) {
428 read_fbo = read.value();
432 auto draw =
ConfigureFBO(gl, destination, GL_DRAW_FRAMEBUFFER);
433 if (!draw.has_value()) {
436 draw_fbo = draw.value();
439 gl.Disable(GL_SCISSOR_TEST);
440 gl.Disable(GL_DEPTH_TEST);
441 gl.Disable(GL_STENCIL_TEST);
443 const IRect source_region = IRect::MakeSize(source->GetSize());
444 const IRect destination_region = IRect::MakeSize(destination->GetSize());
446 gl.BlitFramebuffer(source_region.
GetX(),
447 source_region.
GetY(),
450 destination_region.
GetX(),
451 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