| // Copyright 2013 The Flutter Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "flutter/lib/gpu/texture.h" | |
| #include "flutter/lib/gpu/formats.h" | |
| #include "flutter/lib/ui/painting/image.h" | |
| #include "fml/mapping.h" | |
| #include "impeller/core/allocator.h" | |
| #include "impeller/core/formats.h" | |
| #include "impeller/core/texture.h" | |
| #include "impeller/display_list/dl_image_impeller.h" | |
| #include "third_party/tonic/typed_data/dart_byte_data.h" | |
| namespace flutter { | |
| namespace gpu { | |
| IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, Texture); | |
| Texture::Texture(std::shared_ptr<impeller::Texture> texture) | |
| : texture_(std::move(texture)) {} | |
| Texture::~Texture() = default; | |
| std::shared_ptr<impeller::Texture> Texture::GetTexture() { | |
| return texture_; | |
| } | |
| void Texture::SetCoordinateSystem( | |
| impeller::TextureCoordinateSystem coordinate_system) { | |
| texture_->SetCoordinateSystem(coordinate_system); | |
| } | |
| bool Texture::Overwrite(const tonic::DartByteData& source_bytes) { | |
| const uint8_t* data = static_cast<const uint8_t*>(source_bytes.data()); | |
| auto copy = std::vector<uint8_t>(data, data + source_bytes.length_in_bytes()); | |
| // Texture::SetContents is a bit funky right now. It takes a shared_ptr of a | |
| // mapping and we're forced to copy here. | |
| auto mapping = std::make_shared<fml::DataMapping>(copy); | |
| if (!texture_->SetContents(mapping)) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| size_t Texture::GetBytesPerTexel() { | |
| return impeller::BytesPerPixelForPixelFormat( | |
| texture_->GetTextureDescriptor().format); | |
| } | |
| Dart_Handle Texture::AsImage() const { | |
| // DlImageImpeller isn't compiled in builds with Impeller disabled. If | |
| // Impeller is disabled, it's impossible to get here anyhow, so just ifdef it | |
| // out. | |
| #if IMPELLER_SUPPORTS_RENDERING | |
| auto image = flutter::CanvasImage::Create(); | |
| auto dl_image = impeller::DlImageImpeller::Make(texture_); | |
| image->set_image(dl_image); | |
| auto wrapped = image->CreateOuterWrapping(); | |
| return wrapped; | |
| #else | |
| return Dart_Null(); | |
| #endif | |
| } | |
| } // namespace gpu | |
| } // namespace flutter | |
| //---------------------------------------------------------------------------- | |
| /// Exports | |
| /// | |
| bool InternalFlutterGpu_Texture_Initialize(Dart_Handle wrapper, | |
| flutter::gpu::Context* gpu_context, | |
| int storage_mode, | |
| int format, | |
| int width, | |
| int height, | |
| int sample_count, | |
| int coordinate_system, | |
| bool enable_render_target_usage, | |
| bool enable_shader_read_usage, | |
| bool enable_shader_write_usage) { | |
| impeller::TextureDescriptor desc; | |
| desc.storage_mode = flutter::gpu::ToImpellerStorageMode(storage_mode); | |
| desc.size = {width, height}; | |
| desc.format = flutter::gpu::ToImpellerPixelFormat(format); | |
| desc.usage = {}; | |
| if (enable_render_target_usage) { | |
| desc.usage |= impeller::TextureUsage::kRenderTarget; | |
| } | |
| if (enable_shader_read_usage) { | |
| desc.usage |= impeller::TextureUsage::kShaderRead; | |
| } | |
| if (enable_shader_write_usage) { | |
| desc.usage |= impeller::TextureUsage::kShaderWrite; | |
| } | |
| switch (sample_count) { | |
| case 1: | |
| desc.type = impeller::TextureType::kTexture2D; | |
| desc.sample_count = impeller::SampleCount::kCount1; | |
| break; | |
| case 4: | |
| desc.type = impeller::TextureType::kTexture2DMultisample; | |
| desc.sample_count = impeller::SampleCount::kCount4; | |
| break; | |
| default: | |
| return false; | |
| } | |
| auto texture = | |
| gpu_context->GetContext()->GetResourceAllocator()->CreateTexture(desc); | |
| if (!texture) { | |
| FML_LOG(ERROR) << "Failed to create texture."; | |
| return false; | |
| } | |
| texture->SetCoordinateSystem( | |
| flutter::gpu::ToImpellerTextureCoordinateSystem(coordinate_system)); | |
| auto res = fml::MakeRefCounted<flutter::gpu::Texture>(std::move(texture)); | |
| res->AssociateWithDartWrapper(wrapper); | |
| return true; | |
| } | |
| void InternalFlutterGpu_Texture_SetCoordinateSystem( | |
| flutter::gpu::Texture* wrapper, | |
| int coordinate_system) { | |
| return wrapper->SetCoordinateSystem( | |
| flutter::gpu::ToImpellerTextureCoordinateSystem(coordinate_system)); | |
| } | |
| bool InternalFlutterGpu_Texture_Overwrite(flutter::gpu::Texture* texture, | |
| Dart_Handle source_byte_data) { | |
| return texture->Overwrite(tonic::DartByteData(source_byte_data)); | |
| } | |
| extern int InternalFlutterGpu_Texture_BytesPerTexel( | |
| flutter::gpu::Texture* wrapper) { | |
| return wrapper->GetBytesPerTexel(); | |
| } | |
| Dart_Handle InternalFlutterGpu_Texture_AsImage(flutter::gpu::Texture* wrapper) { | |
| return wrapper->AsImage(); | |
| } |