10 #include "flutter/fml/logging.h"
11 #include "flutter/fml/mapping.h"
12 #include "flutter/fml/trace_event.h"
22 static bool IsDepthStencilFormat(
PixelFormat format) {
47 const TextureDescriptor& desc) {
51 if (usage == render_target && IsDepthStencilFormat(desc.format)) {
59 struct TexImage2DData {
63 std::shared_ptr<const fml::Mapping>
data;
66 switch (pixel_format) {
70 type = GL_UNSIGNED_BYTE;
75 type = GL_UNSIGNED_BYTE;
83 type = GL_UNSIGNED_BYTE;
104 type = GL_UNSIGNED_INT_24_8;
118 std::shared_ptr<const fml::Mapping> mapping)
119 : TexImage2DData(pixel_format) {
120 data = std::move(mapping);
123 bool IsValid()
const {
return is_valid_; }
126 bool is_valid_ =
false;
163 return std::shared_ptr<TextureGLES>(
164 new TextureGLES(std::move(reactor), desc,
true, fbo, std::nullopt));
170 std::optional<GLuint> fbo,
171 std::optional<HandleGLES> external_handle)
173 reactor_(
std::move(reactor)),
174 type_(GetTextureTypeFromDescriptor(GetTextureDescriptor())),
175 handle_(external_handle.has_value()
176 ? external_handle.value()
178 is_wrapped_(is_wrapped),
187 const auto max_size =
188 reactor_->GetProcTable().GetCapabilities()->max_texture_size;
189 if (tex_size.Max(max_size) != max_size) {
191 <<
" would exceed max supported size of " << max_size <<
".";
200 reactor_->CollectHandle(handle_);
209 void TextureGLES::SetLabel(std::string_view label) {
210 reactor_->SetDebugLabel(handle_, std::string{label.data(), label.size()});
214 bool TextureGLES::OnSetContents(
const uint8_t* contents,
221 bool TextureGLES::OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
227 if (mapping->GetSize() == 0u) {
231 if (mapping->GetMapping() ==
nullptr) {
236 VALIDATION_LOG <<
"Incorrect texture usage flags for setting contents on "
237 "this texture object.";
242 VALIDATION_LOG <<
"Cannot set the contents of a wrapped texture.";
248 if (tex_descriptor.size.IsEmpty()) {
252 if (!tex_descriptor.IsValid() ||
253 mapping->GetSize() < tex_descriptor.GetByteSizeOfBaseMipLevel()) {
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 auto data = std::make_shared<TexImage2DData>(tex_descriptor.format,
287 size = tex_descriptor.size,
290 ](
const auto& reactor) {
291 auto gl_handle = reactor.GetGLHandle(handle);
292 if (!gl_handle.has_value()) {
294 <<
"Texture was collected before it could be uploaded to the GPU.";
297 const auto& gl = reactor.GetProcTable();
298 gl.BindTexture(texture_type, gl_handle.value());
299 const GLvoid* tex_data =
nullptr;
301 tex_data =
data->data->GetMapping();
305 TRACE_EVENT1(
"impeller",
"TexImage2DUpload",
"Bytes",
306 std::to_string(
data->data->GetSize()).c_str());
307 gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
308 gl.TexImage2D(texture_target,
310 data->internal_format,
314 data->external_format,
321 slices_initialized_ = reactor_->AddOperation(texture_upload);
322 return slices_initialized_[0];
326 ISize TextureGLES::GetSize()
const {
340 return GL_STENCIL_INDEX8;
342 return GL_DEPTH24_STENCIL8;
344 return GL_DEPTH32F_STENCIL8;
359 void TextureGLES::InitializeContentsIfNecessary()
const {
360 if (!
IsValid() || slices_initialized_[0]) {
363 slices_initialized_[0] =
true;
369 auto size = GetSize();
371 if (size.IsEmpty()) {
375 const auto& gl = reactor_->GetProcTable();
376 auto handle = reactor_->GetGLHandle(handle_);
377 if (!handle.has_value()) {
378 VALIDATION_LOG <<
"Could not initialize the contents of texture.";
386 if (!tex_data.IsValid()) {
390 gl.BindTexture(GL_TEXTURE_2D, handle.value());
392 TRACE_EVENT0(
"impeller",
"TexImage2DInitialization");
393 gl.TexImage2D(GL_TEXTURE_2D,
395 tex_data.internal_format,
399 tex_data.external_format,
407 auto render_buffer_format =
409 if (!render_buffer_format.has_value()) {
413 gl.BindRenderbuffer(GL_RENDERBUFFER, handle.value());
415 TRACE_EVENT0(
"impeller",
"RenderBufferStorageInitialization");
417 gl.RenderbufferStorageMultisampleEXT(
420 render_buffer_format.value(),
425 gl.RenderbufferStorage(
427 render_buffer_format.value(),
441 return reactor_->GetGLHandle(handle_);
446 if (!handle.has_value()) {
449 const auto& gl = reactor_->GetProcTable();
454 if (!target.has_value()) {
458 gl.BindTexture(target.value(), handle.value());
462 gl.BindRenderbuffer(GL_RENDERBUFFER, handle.value());
465 InitializeContentsIfNecessary();
470 slices_initialized_[slice] =
true;
474 return slices_initialized_[slice];
487 VALIDATION_LOG <<
"Generating mipmaps for multisample textures is not "
488 "supported in the GLES backend.";
501 if (!handle.has_value()) {
505 const auto& gl = reactor_->GetProcTable();
518 return GL_COLOR_ATTACHMENT0;
520 return GL_DEPTH_ATTACHMENT;
522 return GL_STENCIL_ATTACHMENT;
532 InitializeContentsIfNecessary();
534 if (!handle.has_value()) {
537 const auto& gl = reactor_->GetProcTable();
541 gl.FramebufferTexture2D(target,
549 gl.FramebufferTexture2DMultisampleEXT(
560 gl.FramebufferRenderbuffer(
573 Scalar TextureGLES::GetYCoordScale()
const {