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;
153 return std::shared_ptr<TextureGLES>(
154 new TextureGLES(std::move(reactor), desc,
true, fbo));
160 std::optional<GLuint> fbo)
162 reactor_(
std::move(reactor)),
163 type_(GetTextureTypeFromDescriptor(GetTextureDescriptor())),
165 is_wrapped_(is_wrapped),
174 const auto max_size =
175 reactor_->GetProcTable().GetCapabilities()->max_texture_size;
176 if (tex_size.Max(max_size) != max_size) {
178 <<
" would exceed max supported size of " << max_size <<
".";
187 reactor_->CollectHandle(handle_);
191 bool TextureGLES::IsValid()
const {
196 void TextureGLES::SetLabel(std::string_view label) {
197 reactor_->SetDebugLabel(handle_, std::string{label.data(), label.size()});
201 bool TextureGLES::OnSetContents(
const uint8_t* contents,
208 bool TextureGLES::OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
214 if (mapping->GetSize() == 0u) {
218 if (mapping->GetMapping() ==
nullptr) {
223 VALIDATION_LOG <<
"Incorrect texture usage flags for setting contents on "
224 "this texture object.";
229 VALIDATION_LOG <<
"Cannot set the contents of a wrapped texture.";
235 if (tex_descriptor.size.IsEmpty()) {
239 if (!tex_descriptor.IsValid() ||
240 mapping->GetSize() < tex_descriptor.GetByteSizeOfBaseMipLevel()) {
245 GLenum texture_target;
246 switch (tex_descriptor.type) {
248 texture_type = GL_TEXTURE_2D;
249 texture_target = GL_TEXTURE_2D;
252 VALIDATION_LOG <<
"Multisample texture uploading is not supported for "
253 "the OpenGLES backend.";
256 texture_type = GL_TEXTURE_CUBE_MAP;
257 texture_target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + slice;
260 texture_type = GL_TEXTURE_EXTERNAL_OES;
261 texture_target = GL_TEXTURE_EXTERNAL_OES;
265 auto data = std::make_shared<TexImage2DData>(tex_descriptor.format,
274 size = tex_descriptor.size,
277 ](
const auto& reactor) {
278 auto gl_handle = reactor.GetGLHandle(handle);
279 if (!gl_handle.has_value()) {
281 <<
"Texture was collected before it could be uploaded to the GPU.";
284 const auto& gl = reactor.GetProcTable();
285 gl.BindTexture(texture_type, gl_handle.value());
286 const GLvoid* tex_data =
nullptr;
288 tex_data =
data->data->GetMapping();
292 TRACE_EVENT1(
"impeller",
"TexImage2DUpload",
"Bytes",
293 std::to_string(
data->data->GetSize()).c_str());
294 gl.PixelStorei(GL_UNPACK_ALIGNMENT, 1);
295 gl.TexImage2D(texture_target,
297 data->internal_format,
301 data->external_format,
308 slices_initialized_ = reactor_->AddOperation(texture_upload);
309 return slices_initialized_[0];
313 ISize TextureGLES::GetSize()
const {
327 return GL_STENCIL_INDEX8;
329 return GL_DEPTH24_STENCIL8;
331 return GL_DEPTH32F_STENCIL8;
346 void TextureGLES::InitializeContentsIfNecessary()
const {
347 if (!IsValid() || slices_initialized_[0]) {
350 slices_initialized_[0] =
true;
356 auto size = GetSize();
358 if (size.IsEmpty()) {
362 const auto& gl = reactor_->GetProcTable();
363 auto handle = reactor_->GetGLHandle(handle_);
364 if (!handle.has_value()) {
365 VALIDATION_LOG <<
"Could not initialize the contents of texture.";
373 if (!tex_data.IsValid()) {
377 gl.BindTexture(GL_TEXTURE_2D, handle.value());
379 TRACE_EVENT0(
"impeller",
"TexImage2DInitialization");
380 gl.TexImage2D(GL_TEXTURE_2D,
382 tex_data.internal_format,
386 tex_data.external_format,
394 auto render_buffer_format =
396 if (!render_buffer_format.has_value()) {
400 gl.BindRenderbuffer(GL_RENDERBUFFER, handle.value());
402 TRACE_EVENT0(
"impeller",
"RenderBufferStorageInitialization");
404 gl.RenderbufferStorageMultisampleEXT(
407 render_buffer_format.value(),
412 gl.RenderbufferStorage(
414 render_buffer_format.value(),
428 return reactor_->GetGLHandle(handle_);
433 if (!handle.has_value()) {
436 const auto& gl = reactor_->GetProcTable();
441 if (!target.has_value()) {
445 gl.BindTexture(target.value(), handle.value());
449 gl.BindRenderbuffer(GL_RENDERBUFFER, handle.value());
452 InitializeContentsIfNecessary();
457 slices_initialized_[slice] =
true;
461 return slices_initialized_[slice];
474 VALIDATION_LOG <<
"Generating mipmaps for multisample textures is not "
475 "supported in the GLES backend.";
488 if (!handle.has_value()) {
492 const auto& gl = reactor_->GetProcTable();
505 return GL_COLOR_ATTACHMENT0;
507 return GL_DEPTH_ATTACHMENT;
509 return GL_STENCIL_ATTACHMENT;
519 InitializeContentsIfNecessary();
521 if (!handle.has_value()) {
524 const auto& gl = reactor_->GetProcTable();
528 gl.FramebufferTexture2D(target,
536 gl.FramebufferTexture2DMultisampleEXT(
547 gl.FramebufferRenderbuffer(
560 Scalar TextureGLES::GetYCoordScale()
const {