|  | // 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(); | 
|  | } |