7 #include "flutter/fml/closure.h"
8 #include "fml/trace_event.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 if (gl.CheckFramebufferStatus(fbo_type) != GL_FRAMEBUFFER_COMPLETE) {
99 if (!gl.BlitFramebuffer.IsAvailable()) {
101 VALIDATION_LOG <<
"Texture blit fallback not implemented yet for GLES2.";
105 GLuint read_fbo = GL_NONE;
106 GLuint draw_fbo = GL_NONE;
107 fml::ScopedCleanupClosure delete_fbos([&gl, &read_fbo, &draw_fbo]() {
108 DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER);
109 DeleteFBO(gl, draw_fbo, GL_DRAW_FRAMEBUFFER);
114 if (!read.has_value()) {
117 read_fbo = read.value();
122 if (!draw.has_value()) {
125 draw_fbo = draw.value();
128 gl.Disable(GL_SCISSOR_TEST);
129 gl.Disable(GL_DEPTH_TEST);
130 gl.Disable(GL_STENCIL_TEST);
148 struct TexImage2DData {
154 explicit TexImage2DData(
PixelFormat pixel_format) {
155 switch (pixel_format) {
159 type = GL_UNSIGNED_BYTE;
164 type = GL_UNSIGNED_BYTE;
172 type = GL_UNSIGNED_BYTE;
182 type = GL_HALF_FLOAT;
193 type = GL_UNSIGNED_INT_24_8;
206 TexImage2DData(
PixelFormat pixel_format, BufferView p_buffer_view)
207 : TexImage2DData(pixel_format) {
211 bool IsValid()
const {
return is_valid_; }
214 bool is_valid_ =
false;
230 VALIDATION_LOG <<
"Incorrect texture usage flags for setting contents on "
231 "this texture object.";
236 VALIDATION_LOG <<
"Cannot set the contents of a wrapped texture.";
242 if (tex_descriptor.size.IsEmpty()) {
246 if (!tex_descriptor.IsValid() ||
256 GLenum texture_target;
257 switch (tex_descriptor.type) {
259 texture_type = GL_TEXTURE_2D;
260 texture_target = GL_TEXTURE_2D;
263 VALIDATION_LOG <<
"Multisample texture uploading is not supported for "
264 "the OpenGLES backend.";
267 texture_type = GL_TEXTURE_CUBE_MAP;
268 texture_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X +
slice;
271 texture_type = GL_TEXTURE_EXTERNAL_OES;
272 texture_target = GL_TEXTURE_EXTERNAL_OES;
276 TexImage2DData
data = TexImage2DData(tex_descriptor.format,
source);
277 if (!
data.IsValid()) {
283 if (!gl_handle.has_value()) {
285 <<
"Texture was collected before it could be uploaded to the GPU.";
289 gl.BindTexture(texture_type, gl_handle.value());
290 const GLvoid* tex_data =
data.buffer_view.GetBuffer()->OnGetContents() +
291 data.buffer_view.GetRange().offset;
296 gl.TexImage2D(texture_target,
298 data.internal_format,
299 tex_descriptor.size.width,
300 tex_descriptor.size.height,
302 data.external_format,
310 gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
311 gl.TexSubImage2D(texture_target,
317 data.external_format,
336 VALIDATION_LOG <<
"Only textures with pixel format RGBA are supported yet.";
343 GLuint read_fbo = GL_NONE;
344 fml::ScopedCleanupClosure delete_fbos(
345 [&gl, &read_fbo]() {
DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER); });
349 if (!read.has_value()) {
352 read_fbo = read.value();
357 rows =
source->GetSize().height](uint8_t*
data,
360 gl.ReadPixels(source_region.GetX(), source_region.GetY(),
361 source_region.GetWidth(), source_region.GetHeight(),
362 GL_RGBA, GL_UNSIGNED_BYTE, data + destination_offset);
363 switch (coord_system) {
364 case TextureCoordinateSystem::kUploadFromHost:
366 case TextureCoordinateSystem::kRenderToTexture:
369 FlipImage(data + destination_offset, source_region.GetWidth(),
370 source_region.GetHeight(), 4);
377 BlitGenerateMipmapCommandGLES::~BlitGenerateMipmapCommandGLES() =
default;
379 std::string BlitGenerateMipmapCommandGLES::GetLabel()
const {
383 bool BlitGenerateMipmapCommandGLES::Encode(
const ReactorGLES& reactor)
const {
384 auto texture_gles = TextureGLES::Cast(texture.get());
385 if (!texture_gles->GenerateMipmap()) {
395 BlitResizeTextureCommandGLES::~BlitResizeTextureCommandGLES() =
default;
397 std::string BlitResizeTextureCommandGLES::GetLabel()
const {
398 return "Resize Texture";
401 bool BlitResizeTextureCommandGLES::Encode(
const ReactorGLES& reactor)
const {
406 if (!gl.BlitFramebuffer.IsAvailable()) {
408 VALIDATION_LOG <<
"Texture blit fallback not implemented yet for GLES2.";
412 destination->SetCoordinateSystem(source->GetCoordinateSystem());
414 GLuint read_fbo = GL_NONE;
415 GLuint draw_fbo = GL_NONE;
416 fml::ScopedCleanupClosure delete_fbos([&gl, &read_fbo, &draw_fbo]() {
417 DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER);
418 DeleteFBO(gl, draw_fbo, GL_DRAW_FRAMEBUFFER);
422 auto read =
ConfigureFBO(gl, source, GL_READ_FRAMEBUFFER);
423 if (!read.has_value()) {
426 read_fbo = read.value();
430 auto draw =
ConfigureFBO(gl, destination, GL_DRAW_FRAMEBUFFER);
431 if (!draw.has_value()) {
434 draw_fbo = draw.value();
437 gl.Disable(GL_SCISSOR_TEST);
438 gl.Disable(GL_DEPTH_TEST);
439 gl.Disable(GL_STENCIL_TEST);
441 const IRect source_region = IRect::MakeSize(source->GetSize());
442 const IRect destination_region = IRect::MakeSize(destination->GetSize());
444 gl.BlitFramebuffer(source_region.
GetX(),
445 source_region.
GetY(),
448 destination_region.
GetX(),
449 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)
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