diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h index a25275a84930989ec4ad296526b94a925c0588f1..60c5fa7093c250f7682efd3fed713ca3456f1ebf 100644 --- a/base/trace_event/builtin_categories.h +++ b/base/trace_event/builtin_categories.h @@ -110,6 +110,7 @@ X("Java") \ X("jni") \ X("jpeg") \ + X("heif") \ X("latency") \ X("latencyInfo") \ X("leveldb") \ diff --git a/build/config/features.gni b/build/config/features.gni index 852ac56a850ec3d451cbeae38d2bfe31a21ac016..a40b012419dfac23e713679e85c8b54c6ab50c72 100644 --- a/build/config/features.gni +++ b/build/config/features.gni @@ -38,6 +38,8 @@ declare_args() { use_gio = is_linux && !is_castos use_blink = !is_ios + + enable_heif_decoder = is_ohos } # # ============================================= diff --git a/cc/base/devtools_instrumentation.cc b/cc/base/devtools_instrumentation.cc index 5837f76aa6dd3b9cc8ad0e0187ef360e5f401cb7..a05c43fb8c9009f66dd4c13d4edbe6788da2266f 100644 --- a/cc/base/devtools_instrumentation.cc +++ b/cc/base/devtools_instrumentation.cc @@ -82,6 +82,11 @@ ScopedImageUploadTask::~ScopedImageUploadTask() { case ImageType::kGif: histogram_name = "Renderer4.ImageUploadTaskDurationUs.Gif"; break; +#if BUILDFLAG(IS_OHOS) + case ImageType::kHeif: + histogram_name = "Renderer4.ImageUploadTaskDurationUs.Heif"; + break; +#endif case ImageType::kIco: histogram_name = "Renderer4.ImageUploadTaskDurationUs.Ico"; break; @@ -131,6 +136,11 @@ ScopedImageDecodeTask::~ScopedImageDecodeTask() { case ImageType::kGif: histogram_name = "Renderer4.ImageDecodeTaskDurationUs.Gif"; break; +#if BUILDFLAG(IS_OHOS) + case ImageType::kHeif: + histogram_name = "Renderer4.ImageUploadTaskDurationUs.Heif"; + break; +#endif case ImageType::kIco: histogram_name = "Renderer4.ImageDecodeTaskDurationUs.Ico"; break; diff --git a/cc/base/devtools_instrumentation.h b/cc/base/devtools_instrumentation.h index f920c3f8c4f68e7a88f574b670158db2bb91fe8a..9a9b5bfe4b5238b25858c5262ee15c89c7fc0c98 100644 --- a/cc/base/devtools_instrumentation.h +++ b/cc/base/devtools_instrumentation.h @@ -72,7 +72,19 @@ class CC_BASE_EXPORT ScopedLayerTask { class CC_BASE_EXPORT ScopedImageTask { public: - enum ImageType { kAvif, kBmp, kGif, kIco, kJpeg, kPng, kWebP, kOther }; + enum ImageType { + kAvif, + kBmp, + kGif, +#if BUILDFLAG(IS_OHOS) + kHeif, +#endif + kIco, + kJpeg, + kPng, + kWebP, + kOther + }; explicit ScopedImageTask(ImageType image_type) : image_type_(image_type), start_time_(base::TimeTicks::Now()) {} diff --git a/cc/paint/image_transfer_cache_entry.cc b/cc/paint/image_transfer_cache_entry.cc index 82f61a1740c05df8fd69027d06562a634ab2bd76..d650a78c3165f7e611e7671470c0c1963dffa0a7 100644 --- a/cc/paint/image_transfer_cache_entry.cc +++ b/cc/paint/image_transfer_cache_entry.cc @@ -629,6 +629,19 @@ ServiceImageTransferCacheEntry::ServiceImageTransferCacheEntry( ServiceImageTransferCacheEntry& ServiceImageTransferCacheEntry::operator=( ServiceImageTransferCacheEntry&& other) = default; +#if BUILDFLAG(IS_OHOS) +bool ServiceImageTransferCacheEntry::BuildFromRGBAHardwareDecodedImage( + GrDirectContext* context, + std::vector> plane_images, + size_t buffer_byte_size) { + context_ = context; + image_ = std::move(plane_images[0]); + size_ = buffer_byte_size; + + return true; +} +#endif + bool ServiceImageTransferCacheEntry::BuildFromHardwareDecodedImage( GrDirectContext* context, std::vector> plane_images, diff --git a/cc/paint/image_transfer_cache_entry.h b/cc/paint/image_transfer_cache_entry.h index fe856452be1406e6b165dfc70a1710642fa98080..4d4e1209f5610592f027bbc8396a9a08b3026769 100644 --- a/cc/paint/image_transfer_cache_entry.h +++ b/cc/paint/image_transfer_cache_entry.h @@ -150,6 +150,12 @@ class CC_PAINT_EXPORT ServiceImageTransferCacheEntry final size_t buffer_byte_size, bool needs_mips); +#if BUILDFLAG(IS_OHOS) + bool BuildFromRGBAHardwareDecodedImage(GrDirectContext* context, + std::vector> plane_images, + size_t buffer_byte_size); +#endif + // ServiceTransferCacheEntry implementation: size_t CachedSize() const final; bool Deserialize(GrDirectContext* context, diff --git a/cc/paint/paint_image.h b/cc/paint/paint_image.h index cf019de89ae99b29b6e610b85a178d1d3307fe87..6fad84873454f9683fdac5ee0e57c7fbcfe6199f 100644 --- a/cc/paint/paint_image.h +++ b/cc/paint/paint_image.h @@ -40,7 +40,19 @@ class PaintImageGenerator; class PaintWorkletInput; class TextureBacking; -enum class ImageType { kPNG, kJPEG, kWEBP, kGIF, kICO, kBMP, kAVIF, kInvalid }; +enum class ImageType { + kPNG, + kJPEG, + kWEBP, + kGIF, + kICO, + kBMP, + kAVIF, +#if BUILDFLAG(IS_OHOS) + kHEIF, +#endif + kInvalid +}; enum class AuxImage : size_t { kDefault = 0, kGainmap = 1 }; static constexpr std::array kAllAuxImages = {AuxImage::kDefault, diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc index 9a9320b0c84689ad2e7e6abd94c118200cb633db..bea4050437d47b1ad6a21b2cbaf7705c5e5aeef5 100644 --- a/cc/tiles/gpu_image_decode_cache.cc +++ b/cc/tiles/gpu_image_decode_cache.cc @@ -2022,6 +2022,16 @@ int GpuImageDecodeCache::CalculateUploadScaleMipLevel( return 0; } +#if BUILDFLAG(IS_OHOS) + // Heif uses hardware-accelerated decode, scaling is not currently supported + // for hardware-accelerated decodes + const auto* image_metadata = + draw_image.paint_image().GetImageHeaderMetadata(); + if (image_metadata && image_metadata->image_type == ImageType::kHEIF) { + return 0; + } +#endif + gfx::Size base_size = draw_image.paint_image().GetSize(aux_image); // Ceil our scaled size so that the mip map generated is guaranteed to be // larger. Take the abs of the scale, as mipmap functions don't handle @@ -2966,6 +2976,13 @@ GpuImageDecodeCache::CreateImageData(const DrawImage& draw_image, DCHECK(!is_bitmap_backed); } +#if BUILDFLAG(IS_OHOS) + if ((image_metadata->image_type == ImageType::kHEIF)) { + do_hardware_accelerated_decode = true; + DCHECK(!is_bitmap_backed); + } +#endif + // Override the estimated size if we are doing hardware decode. if (do_hardware_accelerated_decode) { image_info[kAuxImageIndexDefault].size = diff --git a/cc/tiles/image_decode_cache.h b/cc/tiles/image_decode_cache.h index 82fdd5436cfa6b660975df84d7dadf80ead9dd8b..0cbee0f795e767ca322bd95f15ac718bfe0a848c 100644 --- a/cc/tiles/image_decode_cache.h +++ b/cc/tiles/image_decode_cache.h @@ -90,6 +90,10 @@ class CC_EXPORT ImageDecodeCache { return ScopedImageType::kBmp; case ImageType::kGIF: return ScopedImageType::kGif; +#if BUILDFLAG(IS_OHOS) + case ImageType::kHEIF: + return ScopedImageType::kHeif; +#endif case ImageType::kICO: return ScopedImageType::kIco; case ImageType::kJPEG: diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc index d77358b47be33565fe9492e68f8051c24951ca3c..9489e2035e6d660f77828beacb9b32a41cf38132 100644 --- a/components/viz/service/gl/gpu_service_impl.cc +++ b/components/viz/service/gl/gpu_service_impl.cc @@ -136,6 +136,7 @@ #if BUILDFLAG(IS_OHOS) #include "base/ohos/dynamic_frame_loss_monitor.h" #include "gpu/ipc/common/gpu_surface_id_tracker.h" +#include "media/gpu/ohos/ohos_image_decode_accelerator_worker.h" #endif namespace viz { @@ -400,6 +401,11 @@ GpuServiceImpl::GpuServiceImpl( media::VaapiImageDecodeAcceleratorWorker::Create(); #endif // BUILDFLAG(USE_VAAPI_IMAGE_CODECS) +#if BUILDFLAG(IS_OHOS) + image_decode_accelerator_worker_ = + media::OhosImageDecodeAcceleratorWorker::Create(); +#endif + #if BUILDFLAG(IS_WIN) if (media::SupportMediaFoundationClearPlayback()) { // Initialize the OverlayStateService using the GPUServiceImpl task diff --git a/content/browser/devtools/protocol/system_info_handler.cc b/content/browser/devtools/protocol/system_info_handler.cc index 70b87e42599a4eb6c7507a058a9a3743eb0c2a2e..4d725aea4a5d991f1414ba90e0822e9ded6ec683 100644 --- a/content/browser/devtools/protocol/system_info_handler.cc +++ b/content/browser/devtools/protocol/system_info_handler.cc @@ -200,6 +200,11 @@ ImageDecodeAcceleratorSupportedProfileToProtocol( case gpu::ImageDecodeAcceleratorType::kWebP: image_type = SystemInfo::ImageTypeEnum::Webp; break; +#if BUILDFLAG(IS_OHOS) + case gpu::ImageDecodeAcceleratorType::kHeif: + image_type = SystemInfo::ImageTypeEnum::Unknown; + break; +#endif case gpu::ImageDecodeAcceleratorType::kUnknown: image_type = SystemInfo::ImageTypeEnum::Unknown; break; diff --git a/gpu/command_buffer/common/gpu_memory_buffer_support.cc b/gpu/command_buffer/common/gpu_memory_buffer_support.cc index a749cdb99a052e4c72ce7111387a3a7568711538..579a2c494b46f6e1149635015288ebea9e8aeb93 100644 --- a/gpu/command_buffer/common/gpu_memory_buffer_support.cc +++ b/gpu/command_buffer/common/gpu_memory_buffer_support.cc @@ -48,7 +48,7 @@ bool IsImageSizeValidForGpuMemoryBufferFormat(const gfx::Size& size, case gfx::BufferFormat::YUV_420_BIPLANAR: case gfx::BufferFormat::YUVA_420_TRIPLANAR: case gfx::BufferFormat::P010: -#if BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_OHOS) // Allow odd size for CrOS. // TODO(https://crbug.com/1208788, https://crbug.com/1224781): Merge this // with the path that uses gfx::IsOddHeightMultiPlanarBuffersAllowed. diff --git a/gpu/command_buffer/service/service_transfer_cache.cc b/gpu/command_buffer/service/service_transfer_cache.cc index 2949a725bb47003e14e876f95d2d3c6fce1ae242..2d88242a0cdb35746444d7941474973feecda028 100644 --- a/gpu/command_buffer/service/service_transfer_cache.cc +++ b/gpu/command_buffer/service/service_transfer_cache.cc @@ -282,6 +282,38 @@ void ServiceTransferCache::DeleteAllEntriesForDecoder(int decoder_id) { } } +#if BUILDFLAG(IS_OHOS) +bool ServiceTransferCache::CreateLockedRGBAHardwareDecodedImageEntry( + int decoder_id, + uint32_t entry_id, + ServiceDiscardableHandle handle, + GrDirectContext* context, + std::vector> plane_images, + size_t buffer_byte_size) { + EntryKey key(decoder_id, cc::TransferCacheEntryType::kImage, entry_id); + auto found = entries_.Peek(key); + if (found != entries_.end()) + return false; + + // Create the service-side image transfer cache entry. + auto entry = std::make_unique(); + if (!entry->BuildFromRGBAHardwareDecodedImage( + context, std::move(plane_images), buffer_byte_size)) { + return false; + } + + // Insert it in the transfer cache. + total_size_ += entry->CachedSize(); + if (key.entry_type == cc::TransferCacheEntryType::kImage) { + total_image_count_++; + total_image_size_ += entry->CachedSize(); + } + entries_.Put(key, CacheEntryInternal(handle, std::move(entry))); + EnforceLimits(); + return true; +} +#endif + bool ServiceTransferCache::CreateLockedHardwareDecodedImageEntry( int decoder_id, uint32_t entry_id, diff --git a/gpu/command_buffer/service/service_transfer_cache.h b/gpu/command_buffer/service/service_transfer_cache.h index a38c81a30a4c83878123017b2d4a4226b42fb494..c3c07ccf12752721c7ba5878359731264aac1bfe 100644 --- a/gpu/command_buffer/service/service_transfer_cache.h +++ b/gpu/command_buffer/service/service_transfer_cache.h @@ -85,6 +85,16 @@ class GPU_GLES2_EXPORT ServiceTransferCache size_t buffer_byte_size, bool needs_mips); +#if BUILDFLAG(IS_OHOS) + bool CreateLockedRGBAHardwareDecodedImageEntry( + int decoder_id, + uint32_t entry_id, + ServiceDiscardableHandle handle, + GrDirectContext* context, + std::vector> plane_images, + size_t buffer_byte_size); +#endif + void PurgeMemory( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level); diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc index b22bb939eef0749a53294199532415eef30dfa01..4f80e88b141d6c26e0227eb34f37a990135f7da9 100644 --- a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc +++ b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.cc @@ -198,6 +198,44 @@ std::unique_ptr OzoneImageBackingFactory::CreateSharedImage( return backing; } +#if BUILDFLAG(IS_OHOS) +std::unique_ptr OzoneImageBackingFactory::CreateSharedImage( + const Mailbox& mailbox, + gfx::GpuMemoryBufferHandle handle, + gfx::BufferFormat buffer_format, + gfx::BufferPlane plane, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + GrSurfaceOrigin surface_origin, + SkAlphaType alpha_type, + uint32_t usage, + void* window_buffer) { + DCHECK_EQ(handle.type, gfx::NATIVE_PIXMAP); + ui::SurfaceFactoryOzone* surface_factory = + ui::OzonePlatform::GetInstance()->GetSurfaceFactoryOzone(); + scoped_refptr pixmap = + surface_factory->CreateNativePixmapFromHandle( + kNullSurfaceHandle, size, buffer_format, + std::move(handle.native_pixmap_handle), window_buffer); + if (!pixmap) { + LOG(ERROR) << "[HeifSupport] OzoneImageBackingFactory::CreateSharedImage pixmap is null."; + return nullptr; + } + + const gfx::Size plane_size = gpu::GetPlaneSize(plane, size); + const viz::ResourceFormat plane_format = + viz::GetResourceFormat(GetPlaneBufferFormat(plane, buffer_format)); + auto backing = std::make_unique( + mailbox, viz::SharedImageFormat::SinglePlane(plane_format), plane, + plane_size, color_space, surface_origin, alpha_type, usage, + shared_context_state_.get(), std::move(pixmap), dawn_procs_, workarounds_, + use_passthrough_); + backing->SetCleared(); + + return backing; +} +#endif + std::unique_ptr OzoneImageBackingFactory::CreateSharedImage( const Mailbox& mailbox, viz::SharedImageFormat format, diff --git a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h index 5ef74ea44265035b18454dccdb7a3f814aaeb7a7..827abe74feefa66f1332b159dc940df6acbe486c 100644 --- a/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h +++ b/gpu/command_buffer/service/shared_image/ozone_image_backing_factory.h @@ -77,6 +77,20 @@ class GPU_GLES2_EXPORT OzoneImageBackingFactory uint32_t usage, std::string debug_label) override; +#if BUILDFLAG(IS_OHOS) + std::unique_ptr CreateSharedImage( + const Mailbox& mailbox, + gfx::GpuMemoryBufferHandle handle, + gfx::BufferFormat format, + gfx::BufferPlane plane, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + GrSurfaceOrigin surface_origin, + SkAlphaType alpha_type, + uint32_t usage, + void* window_buffer) override; +#endif + bool IsSupported(uint32_t usage, viz::SharedImageFormat format, const gfx::Size& size, diff --git a/gpu/command_buffer/service/shared_image/shared_image_backing_factory.h b/gpu/command_buffer/service/shared_image/shared_image_backing_factory.h index 2dce6ac307ff576796c96cfc61316dd6d821cb8a..803997c967b658f0733ae8a26174dda87410a84e 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_backing_factory.h +++ b/gpu/command_buffer/service/shared_image/shared_image_backing_factory.h @@ -85,6 +85,20 @@ class GPU_GLES2_EXPORT SharedImageBackingFactory { uint32_t usage, std::string debug_label) = 0; +#if BUILDFLAG(IS_OHOS) + virtual std::unique_ptr CreateSharedImage( + const Mailbox& mailbox, + gfx::GpuMemoryBufferHandle handle, + gfx::BufferFormat format, + gfx::BufferPlane plane, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + GrSurfaceOrigin surface_origin, + SkAlphaType alpha_type, + uint32_t usage, + void* window_buffer) { return nullptr; } +#endif + // Returns true if the factory is supported bool CanCreateSharedImage(uint32_t usage, viz::SharedImageFormat format, diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory.cc b/gpu/command_buffer/service/shared_image/shared_image_factory.cc index 67bf53168e12d94b22d35ac632a720b5bd4de713..4ac97e72abb262cb20b21a9ba7f4e950abc535df 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_factory.cc +++ b/gpu/command_buffer/service/shared_image/shared_image_factory.cc @@ -439,6 +439,46 @@ bool SharedImageFactory::CreateSharedImage( return RegisterBacking(std::move(backing)); } +#if BUILDFLAG(IS_OHOS) +bool SharedImageFactory::CreateSharedImage(const Mailbox& mailbox, + gfx::GpuMemoryBufferHandle handle, + gfx::BufferFormat format, + gfx::BufferPlane plane, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + GrSurfaceOrigin surface_origin, + SkAlphaType alpha_type, + uint32_t usage, + void* window_buffer){ + auto si_format = + viz::SharedImageFormat::SinglePlane(viz::GetResourceFormat(format)); + gfx::GpuMemoryBufferType gmb_type = handle.type; + + auto* factory = GetFactoryByUsage(usage, si_format, size, + /*pixel_data=*/{}, gmb_type); + if (!factory) { + LogGetFactoryFailed(usage, si_format, gmb_type); + return false; + } + + std::unique_ptr backing; + backing = factory->CreateSharedImage( + mailbox, std::move(handle), format, plane, size, color_space, + surface_origin, alpha_type, usage, window_buffer); + if (backing) { + backing->OnWriteSucceeded(); + } else { + LOG(ERROR) << "[HeifSupport] CreateSharedImage[" << backing->GetName() + << "] from handle size=" << size.ToString() + << " usage=" << CreateLabelForSharedImageUsage(usage) + << " buffer_format=" << gfx::BufferFormatToString(format) + << " gmb_type=" << GmbTypeToString(gmb_type); + + } + return RegisterBacking(std::move(backing)); +} +#endif + bool SharedImageFactory::CreateSharedImage(const Mailbox& mailbox, gfx::GpuMemoryBufferHandle handle, gfx::BufferFormat format, diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory.h b/gpu/command_buffer/service/shared_image/shared_image_factory.h index d5a64dce6e694157234c3d9b974372a3fa909774..5df153ae2e598e0a77c1bf47a37536f7345ad05a 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_factory.h +++ b/gpu/command_buffer/service/shared_image/shared_image_factory.h @@ -87,6 +87,17 @@ class GPU_GLES2_EXPORT SharedImageFactory { SkAlphaType alpha_type, uint32_t usage, std::string debug_label); +#if BUILDFLAG(IS_OHOS) + bool CreateSharedImage(const Mailbox& mailbox, + gfx::GpuMemoryBufferHandle handle, + gfx::BufferFormat format, + gfx::BufferPlane plane, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + GrSurfaceOrigin surface_origin, + SkAlphaType alpha_type, + uint32_t usage,void* window_buffer); +#endif bool UpdateSharedImage(const Mailbox& mailbox); bool UpdateSharedImage(const Mailbox& mailbox, std::unique_ptr in_fence); diff --git a/gpu/config/gpu_info.cc b/gpu/config/gpu_info.cc index eb74a10913b699b65067d1a950cf830973f102b6..bb4d35f777ec8a9a15df86a479c91870d0f73ab5 100644 --- a/gpu/config/gpu_info.cc +++ b/gpu/config/gpu_info.cc @@ -76,6 +76,10 @@ const char* ImageDecodeAcceleratorTypeToString( return "JPEG"; case gpu::ImageDecodeAcceleratorType::kWebP: return "WebP"; +#if BUILDFLAG(IS_OHOS) + case gpu::ImageDecodeAcceleratorType::kHeif: + return "Heif"; +#endif case gpu::ImageDecodeAcceleratorType::kUnknown: return "Unknown"; } diff --git a/gpu/config/gpu_info.h b/gpu/config/gpu_info.h index e0d2c9b122d23a7e5aabec714c2ad8755244f1a3..183e5303a9e6935a79fa8bcfeb9bb77e32b6fac7 100644 --- a/gpu/config/gpu_info.h +++ b/gpu/config/gpu_info.h @@ -164,7 +164,12 @@ using VideoEncodeAcceleratorSupportedProfiles = enum class ImageDecodeAcceleratorType { kUnknown = 0, kJpeg = 1, +#if BUILDFLAG(IS_OHOS) + kHeif = 2, + kWebP = 3, +#else kWebP = 2, +#endif kMaxValue = kWebP, }; diff --git a/gpu/ipc/client/image_decode_accelerator_proxy.cc b/gpu/ipc/client/image_decode_accelerator_proxy.cc index 0f7df5704f8cdefad91a028f077fff6b2ec40673..fbe19e78def57941895ca86252a635cdbc1ad8b9 100644 --- a/gpu/ipc/client/image_decode_accelerator_proxy.cc +++ b/gpu/ipc/client/image_decode_accelerator_proxy.cc @@ -114,7 +114,11 @@ bool ImageDecodeAcceleratorProxy::IsImageSupported( if (image_metadata->has_embedded_color_profile) return false; +#if BUILDFLAG(IS_OHOS) + static_assert(static_cast(ImageDecodeAcceleratorType::kMaxValue) == 3, +#else static_assert(static_cast(ImageDecodeAcceleratorType::kMaxValue) == 2, +#endif "IsImageSupported() must be adapted to support all image types " "in ImageDecodeAcceleratorType"); ImageDecodeAcceleratorType image_type = ImageDecodeAcceleratorType::kUnknown; @@ -125,6 +129,11 @@ bool ImageDecodeAcceleratorProxy::IsImageSupported( case cc::ImageType::kWEBP: image_type = ImageDecodeAcceleratorType::kWebP; break; +#if BUILDFLAG(IS_OHOS) + case cc::ImageType::kHEIF: + image_type = ImageDecodeAcceleratorType::kHeif; + break; +#endif default: return false; } @@ -150,6 +159,10 @@ bool ImageDecodeAcceleratorProxy::IsImageSupported( case ImageDecodeAcceleratorType::kWebP: DCHECK(image_metadata->webp_is_non_extended_lossy.has_value()); return image_metadata->webp_is_non_extended_lossy.value(); +#if BUILDFLAG(IS_OHOS) + case ImageDecodeAcceleratorType::kHeif: + return true; +#endif case ImageDecodeAcceleratorType::kUnknown: // Should not reach due to a check above. NOTREACHED(); diff --git a/gpu/ipc/common/gpu_info.mojom b/gpu/ipc/common/gpu_info.mojom index bbd47bfcbda7db2e12fe7c443b79e4d340772bfb..bbfeaafdf7f379cdbe4b98b534d9afd176368c74 100644 --- a/gpu/ipc/common/gpu_info.mojom +++ b/gpu/ipc/common/gpu_info.mojom @@ -104,6 +104,8 @@ struct VideoEncodeAcceleratorSupportedProfile { enum ImageDecodeAcceleratorType { kJpeg, kWebP, + [EnableIf=is_ohos] + kHeif, kUnknown, }; diff --git a/gpu/ipc/common/gpu_info_mojom_traits.cc b/gpu/ipc/common/gpu_info_mojom_traits.cc index a66308711fb5203ce63c5b3c4282d4daeae781fe..321be98dc52536dec24c3971e402bfc2a29b6854 100644 --- a/gpu/ipc/common/gpu_info_mojom_traits.cc +++ b/gpu/ipc/common/gpu_info_mojom_traits.cc @@ -296,6 +296,10 @@ gpu::mojom::ImageDecodeAcceleratorType EnumTraits< return gpu::mojom::ImageDecodeAcceleratorType::kJpeg; case gpu::ImageDecodeAcceleratorType::kWebP: return gpu::mojom::ImageDecodeAcceleratorType::kWebP; +#if BUILDFLAG(IS_OHOS) + case gpu::ImageDecodeAcceleratorType::kHeif: + return gpu::mojom::ImageDecodeAcceleratorType::kHeif; +#endif case gpu::ImageDecodeAcceleratorType::kUnknown: return gpu::mojom::ImageDecodeAcceleratorType::kUnknown; } @@ -313,6 +317,11 @@ bool EnumTraitsBelongsToCurrentThread()); +#if !BUILDFLAG(IS_OHOS) if (!base::FeatureList::IsEnabled( features::kVaapiJpegImageDecodeAcceleration) && !base::FeatureList::IsEnabled( features::kVaapiWebPImageDecodeAcceleration)) { return; } +#endif DCHECK(io_task_runner_->BelongsToCurrentThread()); base::AutoLock lock(lock_); @@ -416,6 +418,149 @@ void ImageDecodeAcceleratorStub::ProcessCompletedDecode( } DCHECK(notify_gl_state_changed); notify_gl_state_changed->RunAndReset(); +#elif BUILDFLAG(IS_OHOS) + // We should notify the SharedContextState that we or Skia may have modified + // the driver's GL state. We put this in a ScopedClosureRunner so that if we + // return early, the SharedContextState ends up in a consistent state. + // TODO(blundell): Determine whether this is still necessary after the + // transition to SharedImage. + notify_gl_state_changed.emplace(base::BindOnce( + [](scoped_refptr scs) { + scs->set_need_context_state_reset(true); + }, + shared_context_state)); + + // Create an SkImage for each plane. + const size_t num_planes = + completed_decode->handle.native_pixmap_handle.planes.size(); + plane_sk_images.resize(num_planes); + for (size_t plane = 0u; plane < num_planes; plane++) { + gfx::Size plane_size = params.output_size; + // Extract the plane out of |completed_decode->handle| and put it in its own + // gfx::GpuMemoryBufferHandle so that we can create a SharedImage for the + // plane. + gfx::GpuMemoryBufferHandle plane_handle; + plane_handle.type = completed_decode->handle.type; + plane_handle.native_pixmap_handle.planes.push_back( + std::move(completed_decode->handle.native_pixmap_handle.planes[plane])); + + // TODO: Right now, we only support RGBA8888 for the output of the decoder, + // We need to support NV12 next. + const auto plane_format = gfx::BufferFormat::RGBA_8888; + + // NOTE: The SurfaceHandle would typically be used to know what gpu adapter + // the buffer belongs to, but here we already have the buffer handle, so it + // should be OK to pass a null SurfaceHandle (it's not clear what + // SurfaceHandle was used to create the original buffers). + gpu::Mailbox mailbox = gpu::Mailbox::GenerateForSharedImage(); + if (!channel_->shared_image_stub()->CreateSharedImage( + mailbox, std::move(plane_handle), plane_format, + gfx::BufferPlane::DEFAULT, plane_size, gfx::ColorSpace(), + kTopLeft_GrSurfaceOrigin, kOpaque_SkAlphaType, + SHARED_IMAGE_USAGE_RASTER | SHARED_IMAGE_USAGE_OOP_RASTERIZATION, + completed_decode->window_buffer)) { + LOG(ERROR) << "[HeifSupport] Could not create SharedImage"; + return; + } + + // Create the SkiaRepresentation::ScopedReadAccess from the SharedImage. + // There is a need to be careful here as the SkiaRepresentation can outlive + // the channel: the representation is effectively owned by the transfer + // cache, which is owned by SharedContextState, which is destroyed by + // GpuChannelManager *after* GpuChannelManager destroys the channels. Hence, + // we cannot supply the channel's SharedImageStub as a MemoryTracker to + // create a SharedImageRepresentationFactory here (the factory creates a + // MemoryTypeTracker instance backed by that MemoryTracker that needs to + // outlive the representation). Instead, we create the Skia representation + // directly using the SharedContextState's MemoryTypeTracker instance. + auto skia_representation = + channel_->gpu_channel_manager()->shared_image_manager()->ProduceSkia( + mailbox, shared_context_state->memory_type_tracker(), + shared_context_state); + + // Note that per the above reasoning, we have to make sure that the factory + // representation doesn't outlive the channel (since it *was* created via + // the channel). We can destroy it now that the skia representation is + // alive. + channel_->shared_image_stub()->factory()->DestroySharedImage(mailbox); + + std::vector begin_semaphores; + std::vector end_semaphores; + auto skia_scoped_access = skia_representation->BeginScopedReadAccess( + &begin_semaphores, &end_semaphores); + + if (!skia_scoped_access) { + LOG(ERROR) << "[HeifSupport] Could not get scoped access to SkiaImageRepresentation"; + return; + } + + // As this SharedImage has just been created, there should not be any + // semaphores. + DCHECK(begin_semaphores.empty()); + DCHECK(end_semaphores.empty()); + + // Create the SkImage, handing over lifetime management of the + // skia image representation and scoped access. + CleanUpContext* resource = new CleanUpContext{}; + resource->main_task_runner = channel_->task_runner(); + resource->shared_context_state = shared_context_state.get(); + resource->skia_representation = std::move(skia_representation); + resource->skia_scoped_access = std::move(skia_scoped_access); + + plane_sk_images[plane] = resource->skia_scoped_access->CreateSkImage( + shared_context_state->gr_context(), CleanUpResource, resource); + if (!plane_sk_images[plane]) { + LOG(ERROR) << "[HeifSupport] Could not create planar SkImage"; + return; + } + } + + // Insert the cache entry in the transfer cache. Note that this section + // validates several of the IPC parameters: |params.raster_decoder_route_id|, + // |params.transfer_cache_entry_id|, |params.discardable_handle_shm_id|, and + // |params.discardable_handle_shm_offset|. + CommandBufferStub* command_buffer = + channel_->LookupCommandBuffer(params.raster_decoder_route_id); + if (!command_buffer) { + LOG(ERROR) << "[HeifSupport] Could not find the command buffer"; + return; + } + scoped_refptr handle_buffer = + command_buffer->GetTransferBuffer(params.discardable_handle_shm_id); + if (!DiscardableHandleBase::ValidateParameters( + handle_buffer.get(), params.discardable_handle_shm_offset)) { + LOG(ERROR) << "[HeifSupport] Could not validate the discardable handle parameters"; + return; + } + DCHECK(command_buffer->decoder_context()); + if (command_buffer->decoder_context()->GetRasterDecoderId() < 0) { + LOG(ERROR) << "[HeifSupport] Could not get the raster decoder ID"; + return; + } + + { + auto* gr_shader_cache = channel_->gpu_channel_manager()->gr_shader_cache(); + absl::optional cache_use; + if (gr_shader_cache) + cache_use.emplace(gr_shader_cache, + base::strict_cast(channel_->client_id())); + DCHECK(shared_context_state->transfer_cache()); + + if (!shared_context_state->transfer_cache() + ->CreateLockedRGBAHardwareDecodedImageEntry( + command_buffer->decoder_context()->GetRasterDecoderId(), + params.transfer_cache_entry_id, + ServiceDiscardableHandle(std::move(handle_buffer), + params.discardable_handle_shm_offset, + params.discardable_handle_shm_id), + shared_context_state->gr_context(), std::move(plane_sk_images), + completed_decode->buffer_byte_size)) { + LOG(ERROR) << "[HeifSupport] Could not create and insert the transfer cache entry"; + return; + } + } + DCHECK(notify_gl_state_changed); + notify_gl_state_changed->RunAndReset(); #else // Right now, we only support Chrome OS because we need to use the // |native_pixmap_handle| member of a GpuMemoryBufferHandle. diff --git a/gpu/ipc/service/image_decode_accelerator_worker.h b/gpu/ipc/service/image_decode_accelerator_worker.h index 9e04d906cd09ef3388224ecadc9c5e4ac58529df..c900076d46c9a14ed3a39913c7e3a6f89bd9800e 100644 --- a/gpu/ipc/service/image_decode_accelerator_worker.h +++ b/gpu/ipc/service/image_decode_accelerator_worker.h @@ -33,6 +33,9 @@ class ImageDecodeAcceleratorWorker { gfx::BufferFormat buffer_format; size_t buffer_byte_size; SkYUVColorSpace yuv_color_space; +#if BUILDFLAG(IS_OHOS) + void* window_buffer; +#endif }; using CompletedDecodeCB = diff --git a/gpu/ipc/service/shared_image_stub.cc b/gpu/ipc/service/shared_image_stub.cc index 558428af8cf31b54bd3298f948f0fd2b32bebb7f..2df04a7713cd2610ec2bf44d495c90106e89731f 100644 --- a/gpu/ipc/service/shared_image_stub.cc +++ b/gpu/ipc/service/shared_image_stub.cc @@ -130,6 +130,41 @@ void SharedImageStub::ExecuteDeferredRequest( } } +#if BUILDFLAG(IS_OHOS) +bool SharedImageStub::CreateSharedImage(const Mailbox& mailbox, + gfx::GpuMemoryBufferHandle handle, + gfx::BufferFormat format, + gfx::BufferPlane plane, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + GrSurfaceOrigin surface_origin, + SkAlphaType alpha_type, + uint32_t usage, + void* window_buffer) { + TRACE_EVENT2("gpu", "SharedImageStub::CreateSharedImage", "width", + size.width(), "height", size.height()); + if (!mailbox.IsSharedImage()) { + LOG(ERROR) << "[HeifSupport] SharedImageStub: Trying to create a SharedImage with a " + "non-SharedImage mailbox."; + OnError(); + return false; + } + if (!MakeContextCurrent()) { + OnError(); + return false; + } + + if (!factory_->CreateSharedImage(mailbox, std::move(handle), format, plane, + size, color_space, surface_origin, + alpha_type, usage, window_buffer)) { + LOG(ERROR) << "[HeifSupport] SharedImageStub: Unable to create shared image"; + OnError(); + return false; + } + return true; +} +#endif + bool SharedImageStub::CreateSharedImage(const Mailbox& mailbox, gfx::GpuMemoryBufferHandle handle, gfx::BufferFormat format, diff --git a/gpu/ipc/service/shared_image_stub.h b/gpu/ipc/service/shared_image_stub.h index bb01f2b06920d2e6c60673f376e58ac5ef821a74..c3a5a4632da702db838decd15a0d872794fcc8a8 100644 --- a/gpu/ipc/service/shared_image_stub.h +++ b/gpu/ipc/service/shared_image_stub.h @@ -49,6 +49,19 @@ class GPU_IPC_SERVICE_EXPORT SharedImageStub : public MemoryTracker { SharedImageDestructionCallback GetSharedImageDestructionCallback( const Mailbox& mailbox); +#if BUILDFLAG(IS_OHOS) + bool CreateSharedImage(const Mailbox& mailbox, + gfx::GpuMemoryBufferHandle handle, + gfx::BufferFormat format, + gfx::BufferPlane plane, + const gfx::Size& size, + const gfx::ColorSpace& color_space, + GrSurfaceOrigin surface_origin, + SkAlphaType alpha_type, + uint32_t usage, + void* window_buffer); +#endif + bool CreateSharedImage(const Mailbox& mailbox, gfx::GpuMemoryBufferHandle handle, gfx::BufferFormat format, diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index 4e5c6b2eabb576b5a2ae7f965e8e804b1f5a6030..040b29bc9a04fee8d5b2222a8f573b36bc4cd96b 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn @@ -190,8 +190,6 @@ component("gpu") { import("//build/config/ohos/config.gni") sources += [ - "ohos/ohos_video_decoder.h", - "ohos/ohos_video_decoder.cc", "ohos/codec_allocator.cc", "ohos/codec_allocator.h", "ohos/codec_buffer_wait_coordinator.cc", @@ -208,16 +206,20 @@ component("gpu") { "ohos/direct_shared_image_video_provider.h", "ohos/frame_info_helper.cc", "ohos/frame_info_helper.h", + "ohos/ohos_video_decoder.h", + "ohos/ohos_video_decoder.cc", + "ohos/ohos_video_encode_accelerator.cc", + "ohos/ohos_video_encode_accelerator.h", "ohos/shared_image_video_provider.cc", "ohos/shared_image_video_provider.h", "ohos/video_frame_factory.h", "ohos/video_frame_factory_impl.cc", "ohos/video_frame_factory_impl.h", - "ohos/ohos_video_encode_accelerator.cc", - "ohos/ohos_video_encode_accelerator.h", ] include_dirs = ohos_src_includes lib_dirs = ohos_libs_dir + + public_deps += [ "//media/gpu/ohos" ] } if (use_v4l2_codec) { diff --git a/media/gpu/ohos/BUILD.gn b/media/gpu/ohos/BUILD.gn new file mode 100644 index 0000000000000000000000000000000000000000..1555a10940a5d15f516f654f304ac14c426d12bd --- /dev/null +++ b/media/gpu/ohos/BUILD.gn @@ -0,0 +1,44 @@ +# Copyright 2018 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/features.gni") +import("//build/config/ui.gni") +import("//media/gpu/args.gni") +import("//media/media_options.gni") +import("//testing/test.gni") +import("//tools/generate_stubs/rules.gni") +import("//ui/gl/features.gni") + +source_set("ohos") { + defines = [ "MEDIA_GPU_IMPLEMENTATION" ] + sources = [ + "ohos_heif_image_decoder.cc", + "ohos_heif_image_decoder.h", + "ohos_image_decode_accelerator_worker.cc", + "ohos_image_decode_accelerator_worker.h", + "ohos_image_decoder.cc", + "ohos_image_decoder.h", + ] + + deps = [ + "//base", + "//gpu/command_buffer/service:gles2", + "//gpu/config", + "//gpu/ipc/common", + "//gpu/ipc/service", + "//media/gpu:common", + "//media/parsers", + "//mojo/public/cpp/bindings", + "//third_party/libvpx:libvpxrc", + "//third_party/libyuv", + "//ui/gfx", + "//ui/gfx/geometry", + ] + + public_deps = [ + "//media", + "//skia", + "//ui/gl", + ] +} diff --git a/media/gpu/ohos/ohos_heif_image_decoder.cc b/media/gpu/ohos/ohos_heif_image_decoder.cc new file mode 100644 index 0000000000000000000000000000000000000000..ab1467902236399dd932152ded29e5b107a5590f --- /dev/null +++ b/media/gpu/ohos/ohos_heif_image_decoder.cc @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "media/gpu/ohos/ohos_heif_image_decoder.h" + +#include "base/files/scoped_file.h" +#include "base/posix/eintr_wrapper.h" +#include "third_party/ohos_ndk/includes/ohos_adapter/ohos_adapter_helper.h" +#include "ui/gfx/linux/native_pixmap_dmabuf.h" + +namespace media { + +OhosHeifImageDecoder::OhosHeifImageDecoder() : OhosImageDecoder() {} + +OhosHeifImageDecoder::~OhosHeifImageDecoder() = default; + +gpu::ImageDecodeAcceleratorType OhosHeifImageDecoder::GetType() const { + return gpu::ImageDecodeAcceleratorType::kHeif; +} + +SkYUVColorSpace OhosHeifImageDecoder::GetYUVColorSpace() const { + return SkYUVColorSpace::kIdentity_SkYUVColorSpace; +} + +std::unique_ptr +OhosHeifImageDecoder::ExportAsNativePixmapDmaBuf( + OhosImageDecodeStatus* status) { + if (!GetOhosImageDecoderAdapter()->GetNativeWindowBuffer()) { + LOG(ERROR) << "[HeifSupport] Fail to get native window surface buffer."; + *status = OhosImageDecodeStatus::kCannotGetImage; + return nullptr; + } + + gfx::NativePixmapHandle handle{}; + // TODO: Get yuv flag from ohos and the plane count is 3 for NV12 now. + bool is_yuv_format = false; + int planes_count = + is_yuv_format ? GetOhosImageDecoderAdapter()->GetPlanesCount() : 1; + for (auto num = 0; num < planes_count; num++) { + auto plane_fd = base::ScopedFD( + HANDLE_EINTR(dup(GetOhosImageDecoderAdapter()->GetFd()))); + handle.planes.emplace_back(GetOhosImageDecoderAdapter()->GetStride(), + GetOhosImageDecoderAdapter()->GetOffset(), + GetOhosImageDecoderAdapter()->GetSize(), + std::move(plane_fd)); + } + + std::unique_ptr exported_pixmap = + std::make_unique(); + exported_pixmap->byte_size = GetOhosImageDecoderAdapter()->GetSize(); + // TODO: To support YUV(NV12) format. + LOG(INFO) << "[HeifSupport] ExportAsNativePixmapDmaBuf windowbuffer " << GetOhosImageDecoderAdapter()->GetNativeWindowBuffer(); + exported_pixmap->pixmap = base::MakeRefCounted( + gfx::Size(GetOhosImageDecoderAdapter()->GetImageWidth(), + GetOhosImageDecoderAdapter()->GetImageHeight()), + is_yuv_format ? gfx::BufferFormat::YUV_420_BIPLANAR + : gfx::BufferFormat::RGBA_8888, + std::move(handle), GetOhosImageDecoderAdapter()->GetNativeWindowBuffer()); + + *status = OhosImageDecodeStatus::kSuccess; + + return exported_pixmap; +} + +} // namespace media \ No newline at end of file diff --git a/media/gpu/ohos/ohos_heif_image_decoder.h b/media/gpu/ohos/ohos_heif_image_decoder.h new file mode 100644 index 0000000000000000000000000000000000000000..68bce0a6b581ce2f691811e23e675952a48d2e10 --- /dev/null +++ b/media/gpu/ohos/ohos_heif_image_decoder.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MEDIA_GPU_OHOS_OHOS_HEIF_IMAGE_DECODER_H_ +#define MEDIA_GPU_OHOS_OHOS_HEIF_IMAGE_DECODER_H_ + +#include + +#include + +#include "base/containers/span.h" +#include "base/functional/callback_forward.h" +#include "base/memory/scoped_refptr.h" +#include "media/gpu/ohos/ohos_image_decoder.h" + +namespace media { + +class OhosHeifImageDecoder : public OhosImageDecoder { + public: + explicit OhosHeifImageDecoder(); + OhosHeifImageDecoder(const OhosHeifImageDecoder&) = delete; + OhosHeifImageDecoder& operator=(const OhosHeifImageDecoder&) = delete; + + virtual ~OhosHeifImageDecoder(); + + // OhosImageDecoder implementation. + gpu::ImageDecodeAcceleratorType GetType() const override; + SkYUVColorSpace GetYUVColorSpace() const override; + + std::unique_ptr ExportAsNativePixmapDmaBuf( + OhosImageDecodeStatus* status) override; + + private: +}; + +} // namespace media + +#endif // MEDIA_GPU_OHOS_OHOS_HEIF_IMAGE_DECODER_H_ \ No newline at end of file diff --git a/media/gpu/ohos/ohos_image_decode_accelerator_worker.cc b/media/gpu/ohos/ohos_image_decode_accelerator_worker.cc new file mode 100644 index 0000000000000000000000000000000000000000..b0a1f5d3970a63227ebac10df266625d7c8df629 --- /dev/null +++ b/media/gpu/ohos/ohos_image_decode_accelerator_worker.cc @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "base/containers/span.h" +#include "base/feature_list.h" +#include "base/functional/bind.h" +#include "base/location.h" +#include "base/logging.h" +#include "base/memory/ptr_util.h" +#include "base/metrics/histogram_macros.h" +#include "base/task/sequenced_task_runner.h" +#include "base/task/thread_pool.h" +#include "base/trace_event/trace_event.h" +#include "gpu/config/gpu_finch_features.h" +#include "media/gpu/macros.h" +#include "media/gpu/ohos/ohos_heif_image_decoder.h" +#include "media/gpu/ohos/ohos_image_decode_accelerator_worker.h" +#include "media/parsers/webp_parser.h" +#include "mojo/public/cpp/bindings/callback_helpers.h" +#include "string.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/gpu_memory_buffer.h" +#include "ui/gfx/linux/native_pixmap_dmabuf.h" +#include "ui/gfx/native_pixmap_handle.h" + +namespace media { + +namespace { +// Uses |decoder| to decode the image corresponding to |encoded_data|. +// |decode_cb| is called when finished or when an error is encountered. We don't +// support decoding to scale, so |output_size| is only used for tracing. +void DecodeTask( + OhosImageDecoder* decoder, + std::vector encoded_data, + const gfx::Size& output_size, + gpu::ImageDecodeAcceleratorWorker::CompletedDecodeCB decode_cb) { + TRACE_EVENT2("heif", "OhosImageDecodeAcceleratorWorker::DecodeTask", + "encoded_bytes", encoded_data.size(), "output_size", + output_size.ToString()); + gpu::ImageDecodeAcceleratorWorker::CompletedDecodeCB scoped_decode_callback = + mojo::WrapCallbackWithDefaultInvokeIfNotRun(std::move(decode_cb), + nullptr); + LOG(INFO) << "[HeifSupport] OhosImageDecodeAcceleratorWorker DecodeTask."; + if (!decoder) { + LOG(ERROR) << "[HeifSupport] No decoder is available for supplied image"; + return; + } + + OhosImageDecodeStatus status = decoder->Decode(encoded_data); + if (status != OhosImageDecodeStatus::kSuccess) { + LOG(ERROR) << "[HeifSupport] Failed to decode - status = " + << static_cast(status); + + return; + } + // Export the decode result as a NativePixmap. + std::unique_ptr exported_pixmap = + decoder->ExportAsNativePixmapDmaBuf(&status); + if (status != OhosImageDecodeStatus::kSuccess) { + LOG(ERROR) << "[HeifSupport] Failed to export surface - status = " + << static_cast(status); + return; + } + DCHECK(exported_pixmap); + DCHECK(exported_pixmap->pixmap); + if (exported_pixmap->pixmap->GetBufferSize() != output_size) { + LOG(ERROR) << "[HeifSupport] Scaling is not supported" << "GetBufferSize " + << exported_pixmap->pixmap->GetBufferSize().ToString() + << ", output_size " << output_size.ToString(); + return; + } + + // Output the decoded data. + gfx::NativePixmapHandle pixmap_handle = + exported_pixmap->pixmap->ExportHandle(); + // If a dup() failed while exporting the handle, we would get no planes. + if (pixmap_handle.planes.empty()) { + LOG(ERROR) << "[HeifSupport] Could not export the NativePixmapHandle"; + return; + } + + auto result = + std::make_unique(); + result->handle.type = gfx::GpuMemoryBufferType::NATIVE_PIXMAP; + result->handle.native_pixmap_handle = std::move(pixmap_handle); + result->visible_size = exported_pixmap->pixmap->GetBufferSize(); + result->buffer_format = exported_pixmap->pixmap->GetBufferFormat(); + result->buffer_byte_size = exported_pixmap->byte_size; + result->yuv_color_space = decoder->GetYUVColorSpace(); + result->window_buffer = exported_pixmap->pixmap->GetWindowBuffer(); + + std::move(scoped_decode_callback).Run(std::move(result)); +} + +} // namespace + +// static +std::unique_ptr +OhosImageDecodeAcceleratorWorker::Create() { + OhosImageDecoderVector decoders; + + auto heif_image_decoder = std::make_unique(); + + if (heif_image_decoder->Initialize()) { + decoders.push_back(std::move(heif_image_decoder)); + } + + // If there are no decoders due to disabled flags or initialization failure, + // return nullptr. + if (decoders.empty()) { + return nullptr; + } + + return base::WrapUnique( + new OhosImageDecodeAcceleratorWorker(std::move(decoders))); +} + +OhosImageDecodeAcceleratorWorker::OhosImageDecodeAcceleratorWorker( + OhosImageDecoderVector decoders) { + DETACH_FROM_SEQUENCE(io_sequence_checker_); + decoder_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner({}); + DCHECK(decoder_task_runner_); + + DCHECK(!decoders.empty()); + for (auto& decoder : decoders) { + supported_profiles_.push_back(decoder->GetSupportedProfile()); + const gpu::ImageDecodeAcceleratorType type = decoder->GetType(); + decoders_[type] = std::move(decoder); + } +} + +OhosImageDecodeAcceleratorWorker::~OhosImageDecodeAcceleratorWorker() { + DCHECK_CALLED_ON_VALID_SEQUENCE(main_sequence_checker_); + DCHECK(decoder_task_runner_); + for (auto& decoder : decoders_) { + decoder_task_runner_->DeleteSoon(FROM_HERE, std::move(decoder.second)); + } +} + +gpu::ImageDecodeAcceleratorSupportedProfiles +OhosImageDecodeAcceleratorWorker::GetSupportedProfiles() { + return supported_profiles_; +} + +OhosImageDecoder* OhosImageDecodeAcceleratorWorker::GetDecoderForImage( + const std::vector& encoded_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(io_sequence_checker_); + auto result = decoders_.end(); + result = decoders_.find(gpu::ImageDecodeAcceleratorType::kHeif); + + return result == decoders_.end() ? nullptr : result->second.get(); +} + +void OhosImageDecodeAcceleratorWorker::Decode(std::vector encoded_data, + const gfx::Size& output_size, + CompletedDecodeCB decode_cb) { + DCHECK_CALLED_ON_VALID_SEQUENCE(io_sequence_checker_); + DCHECK(decoder_task_runner_); + // We defer checking for a null |decoder| until DecodeTask() because the + // gpu::ImageDecodeAcceleratorWorker interface mandates that the callback be + // called asynchronously. + LOG(INFO) << "[HeifSupport] OhosImageDecodeAcceleratorWorker::Decode."; + OhosImageDecoder* decoder = GetDecoderForImage(encoded_data); + decoder_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&DecodeTask, decoder, std::move(encoded_data), + output_size, std::move(decode_cb))); +} + +} // namespace media \ No newline at end of file diff --git a/media/gpu/ohos/ohos_image_decode_accelerator_worker.h b/media/gpu/ohos/ohos_image_decode_accelerator_worker.h new file mode 100644 index 0000000000000000000000000000000000000000..edd0fc39932c09610228602fee19c1469a7569e7 --- /dev/null +++ b/media/gpu/ohos/ohos_image_decode_accelerator_worker.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MEDIA_GPU_OHOS_OHOS_IMAGE_DECODE_ACCELERATOR_WORKER_H_ +#define MEDIA_GPU_OHOS_OHOS_IMAGE_DECODE_ACCELERATOR_WORKER_H_ + +#include + +#include +#include +#include + +#include "base/containers/small_map.h" +#include "base/memory/scoped_refptr.h" +#include "base/sequence_checker.h" +#include "gpu/config/gpu_info.h" +#include "gpu/ipc/service/image_decode_accelerator_worker.h" + +namespace base { +class SequencedTaskRunner; +} + +namespace gfx { +class Size; +} + +namespace media { + +class OhosImageDecoder; + +using OhosImageDecoderVector = std::vector>; + +using OhosImageDecoderMap = + base::small_map>>; + +class OhosImageDecodeAcceleratorWorker + : public gpu::ImageDecodeAcceleratorWorker { + public: + // Creates a OhosImageDecodeAcceleratorWorker and attempts to initialize the + // internal state. Returns nullptr if initialization fails. + static std::unique_ptr Create(); + + OhosImageDecodeAcceleratorWorker(const OhosImageDecodeAcceleratorWorker&) = + delete; + OhosImageDecodeAcceleratorWorker& operator=( + const OhosImageDecodeAcceleratorWorker&) = delete; + + ~OhosImageDecodeAcceleratorWorker() override; + + gpu::ImageDecodeAcceleratorSupportedProfiles GetSupportedProfiles() override; + void Decode(std::vector encoded_data, + const gfx::Size& output_size, + CompletedDecodeCB decode_cb) override; + + private: + explicit OhosImageDecodeAcceleratorWorker(OhosImageDecoderVector decoders); + + OhosImageDecoder* GetDecoderForImage( + const std::vector& encoded_data); + + // We delegate the decoding to the appropriate decoder in |decoders_| which + // are used and destroyed on |decoder_task_runner_|. + OhosImageDecoderMap decoders_; + gpu::ImageDecodeAcceleratorSupportedProfiles supported_profiles_; + scoped_refptr decoder_task_runner_; + + SEQUENCE_CHECKER(main_sequence_checker_); + SEQUENCE_CHECKER(io_sequence_checker_); +}; + +} // namespace media + +#endif // MEDIA_GPU_OHOS_OHOS_IMAGE_DECODE_ACCELERATOR_WORKER_H_ diff --git a/media/gpu/ohos/ohos_image_decoder.cc b/media/gpu/ohos/ohos_image_decoder.cc new file mode 100644 index 0000000000000000000000000000000000000000..352025f43436fc9a8bcc80a262f29e50db2dd873 --- /dev/null +++ b/media/gpu/ohos/ohos_image_decoder.cc @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "media/gpu/ohos/ohos_image_decoder.h" + +#include + +#include "base/logging.h" +#include "media/gpu/macros.h" +#include "third_party/ohos_ndk/includes/ohos_adapter/ohos_adapter_helper.h" +#include "ui/gfx/geometry/size.h" + +namespace media { + +namespace { + +// Size limitation of OHOS hardware image decoder. +constexpr int kMaxDecodedImageWidth = 4096; +constexpr int kMaxDecodedImageHeight = 4096; +constexpr int kMinDecodedImageWidth = 128; +constexpr int kMinDecodedImageHeight = 128; + +} // namespace + +OhosImageDecoder::OhosImageDecoder() = default; +OhosImageDecoder::~OhosImageDecoder() = default; + +bool OhosImageDecoder::Initialize() { + OhosImageDecoderAdapter_ = OHOS::NWeb::OhosAdapterHelper::GetInstance() + .CreateOhosImageDecoderAdapter(); + return !!OhosImageDecoderAdapter_; +} + +OhosImageDecodeStatus OhosImageDecoder::Decode( + base::span encoded_image) { + LOG(INFO) << "[HeifSupport] OhosImageDecoder::Decode."; + if (!OhosImageDecoderAdapter_->DecodeToPixelMap(encoded_image.data(), + encoded_image.size())) { + LOG(ERROR) << "[HeifSupport] OhosImageDecoder::Decode is failed."; + return OhosImageDecodeStatus::kCannotGetImage; + } + + return OhosImageDecodeStatus::kSuccess; +} + +gpu::ImageDecodeAcceleratorSupportedProfile +OhosImageDecoder::GetSupportedProfile() const { + gpu::ImageDecodeAcceleratorSupportedProfile profile; + profile.image_type = GetType(); + profile.min_encoded_dimensions = + gfx::Size(kMinDecodedImageWidth, kMinDecodedImageHeight); + profile.max_encoded_dimensions = + gfx::Size(kMaxDecodedImageWidth, kMaxDecodedImageHeight); + DCHECK_NE(gpu::ImageDecodeAcceleratorType::kUnknown, profile.image_type); + + profile.subsamplings.push_back(gpu::ImageDecodeAcceleratorSubsampling::k420); + return profile; +} + +std::unique_ptr +OhosImageDecoder::ExportAsNativePixmapDmaBuf(OhosImageDecodeStatus* status) { + return nullptr; +} + +OHOS::NWeb::OhosImageDecoderAdapter* OhosImageDecoder::GetOhosImageDecoderAdapter() { + return OhosImageDecoderAdapter_.get(); +} + +} // namespace media \ No newline at end of file diff --git a/media/gpu/ohos/ohos_image_decoder.h b/media/gpu/ohos/ohos_image_decoder.h new file mode 100644 index 0000000000000000000000000000000000000000..5a593f5dce85775e7f2962a44ae6aa9d521d2309 --- /dev/null +++ b/media/gpu/ohos/ohos_image_decoder.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MEDIA_GPU_OHOS_OHOS_IMAGE_DECODER_H_ +#define MEDIA_GPU_OHOS_OHOS_IMAGE_DECODER_H_ + +#include + +#include + +#include "base/containers/span.h" +#include "base/functional/callback_forward.h" +#include "base/memory/scoped_refptr.h" +#include "gpu/config/gpu_info.h" +#include "third_party/skia/include/core/SkImageInfo.h" + +namespace gfx { +class NativePixmapDmaBuf; +} // namespace gfx + +namespace OHOS::NWeb { +class OhosImageDecoderAdapter; +} + +namespace media { + +struct NativePixmapAndSizeInfo { + NativePixmapAndSizeInfo() = default; + ~NativePixmapAndSizeInfo() = default; + + // The size of the underlying Buffer Object. A use case for this is when an + // image decode is requested and the caller needs to know the size of the + // allocated buffer for caching purposes. + size_t byte_size = 0u; + + // Contains the information needed to use the surface in a graphics API, + // including the visible size (|pixmap|->GetBufferSize()) which should be no + // larger than |va_surface_resolution|. + scoped_refptr pixmap; +}; + +enum class OhosImageDecodeStatus : uint32_t { + kSuccess, + kUnsupportedSubsampling, + kExecuteDecodeFailed, + kCannotGetImage, + kInvalidState, +}; + +// This class abstracts the idea of VA-API format-specific decoders. It is the +// responsibility of each subclass to initialize |vaapi_wrapper_| appropriately +// for the purpose of performing hardware-accelerated image decodes of a +// particular format (e.g. JPEG or WebP). Objects of this class are not +// thread-safe, but they are also not thread-affine, i.e., the caller is free to +// call the methods on any thread, but calls must be synchronized externally. +class OhosImageDecoder { + public: + explicit OhosImageDecoder(); + OhosImageDecoder(const OhosImageDecoder&) = delete; + OhosImageDecoder& operator=(const OhosImageDecoder&) = delete; + + virtual ~OhosImageDecoder(); + + // Initializes |vaapi_wrapper_| in kDecode mode with the + // appropriate VAAPI profile and |error_uma_cb| for error reporting. + virtual bool Initialize(); + + virtual OhosImageDecodeStatus Decode( + base::span encoded_image); + + virtual gpu::ImageDecodeAcceleratorType GetType() const = 0; + + virtual SkYUVColorSpace GetYUVColorSpace() const = 0; + + // Returns the image profile supported by this decoder. + virtual gpu::ImageDecodeAcceleratorSupportedProfile GetSupportedProfile() + const; + + OHOS::NWeb::OhosImageDecoderAdapter* GetOhosImageDecoderAdapter(); + + // Exports the decoded data from the last Decode() call as a + // gfx::NativePixmapDmaBuf. Returns nullptr on failure and sets *|status| to + // the reason for failure. On success, the image decoder gives up ownership of + // the buffer underlying the NativePixmapDmaBuf. + virtual std::unique_ptr ExportAsNativePixmapDmaBuf( + OhosImageDecodeStatus* status); + private: + std::unique_ptr OhosImageDecoderAdapter_; +}; + +} // namespace media + +#endif // MEDIA_GPU_VAAPI_VAAPI_IMAGE_DECODER_H_ diff --git a/net/base/mime_util.cc b/net/base/mime_util.cc index d4ac4b84f8f033be4fb09ab5df3fc55a0728d0bf..7a9d4ab67632fc5b9029e19657a8f8ecb9608131 100644 --- a/net/base/mime_util.cc +++ b/net/base/mime_util.cc @@ -161,6 +161,9 @@ static const MimeInfo kPrimaryMappings[] = { {"audio/webm", "webm"}, {"audio/x-m4a", "m4a"}, {"image/avif", "avif"}, +#if BUILDFLAG(IS_OHOS) + {"image/heif", "heif,heic,hevc"}, +#endif {"image/gif", "gif"}, {"image/jpeg", "jpeg,jpg"}, {"image/png", "png"}, @@ -664,6 +667,9 @@ static const char* const kStandardImageTypes[] = {"image/avif", "image/bmp", "image/cis-cod", "image/gif", +#if BUILDFLAG(IS_OHOS) + "image/heif", +#endif "image/ief", "image/jpeg", "image/webp", diff --git a/ohos_build/build.sh b/ohos_build/build.sh index e61ffcd2e819af7031fbe639fa4ec7ff85509554..d79b22ec99b82af6037ba0f23b3f970e011abc8a 100755 --- a/ohos_build/build.sh +++ b/ohos_build/build.sh @@ -214,12 +214,12 @@ fi if [ $buildcount = 0 ]; then #buildcount=$(grep processor /proc/cpuinfo | wc -l) - buildcount=40 + buildcount=8 fi if [ $buildccache = 1 ]; then if [ $buildcount = 0 ]; then - buildcount=64 + buildcount=8 fi GN_ARGS="cc_wrapper=\"ccache\" clang_use_chrome_plugins=false linux_use_bundled_binutils=false" export CCACHE_CPP2=yes diff --git a/ui/gfx/linux/native_pixmap_dmabuf.cc b/ui/gfx/linux/native_pixmap_dmabuf.cc index 3ae93496fb3a797c454473ea4bcfdd6297349ef0..92344048efb776fdd7d920e216b6f7f54adc5e70 100644 --- a/ui/gfx/linux/native_pixmap_dmabuf.cc +++ b/ui/gfx/linux/native_pixmap_dmabuf.cc @@ -12,8 +12,15 @@ namespace gfx { NativePixmapDmaBuf::NativePixmapDmaBuf(const gfx::Size& size, gfx::BufferFormat format, +#if BUILDFLAG(IS_OHOS) + gfx::NativePixmapHandle handle, + void* window_buffer) + + : size_(size), format_(format), handle_(std::move(handle)), native_window_buffer_(window_buffer) {} +#else gfx::NativePixmapHandle handle) : size_(size), format_(format), handle_(std::move(handle)) {} +#endif NativePixmapDmaBuf::~NativePixmapDmaBuf() {} diff --git a/ui/gfx/linux/native_pixmap_dmabuf.h b/ui/gfx/linux/native_pixmap_dmabuf.h index f12d4f5eac89d5362762d7d710f3d19851aa334f..04e13282a3f3f3cf19b94754743506ff46b4bf33 100644 --- a/ui/gfx/linux/native_pixmap_dmabuf.h +++ b/ui/gfx/linux/native_pixmap_dmabuf.h @@ -23,7 +23,12 @@ class GFX_EXPORT NativePixmapDmaBuf : public gfx::NativePixmap { public: NativePixmapDmaBuf(const gfx::Size& size, gfx::BufferFormat format, +#if BUILDFLAG(IS_OHOS) + gfx::NativePixmapHandle handle, + void* window_buffer = nullptr); +#else gfx::NativePixmapHandle handle); +#endif NativePixmapDmaBuf(const NativePixmapDmaBuf&) = delete; NativePixmapDmaBuf& operator=(const NativePixmapDmaBuf&) = delete; @@ -45,6 +50,9 @@ class GFX_EXPORT NativePixmapDmaBuf : public gfx::NativePixmap { std::vector acquire_fences, std::vector release_fences) override; gfx::NativePixmapHandle ExportHandle() override; +#if BUILDFLAG(IS_OHOS) + void* GetWindowBuffer() override { return native_window_buffer_; } +#endif protected: ~NativePixmapDmaBuf() override; @@ -53,6 +61,9 @@ class GFX_EXPORT NativePixmapDmaBuf : public gfx::NativePixmap { gfx::Size size_; gfx::BufferFormat format_; gfx::NativePixmapHandle handle_; +#if BUILDFLAG(IS_OHOS) + void* native_window_buffer_; +#endif }; } // namespace gfx diff --git a/ui/gfx/native_pixmap.h b/ui/gfx/native_pixmap.h index 92efc95645a70a8af896c47b8965c24a3079b626..4809da8f694656d677e67314c176dd8c5658594c 100644 --- a/ui/gfx/native_pixmap.h +++ b/ui/gfx/native_pixmap.h @@ -66,6 +66,10 @@ class NativePixmap : public base::RefCountedThreadSafe { // Any file descriptors in the exported handle are owned by the caller. virtual gfx::NativePixmapHandle ExportHandle() = 0; +#if BUILDFLAG(IS_OHOS) + virtual void* GetWindowBuffer() { return nullptr; } +#endif + protected: virtual ~NativePixmap() {} diff --git a/ui/ozone/common/native_pixmap_egl_binding.cc b/ui/ozone/common/native_pixmap_egl_binding.cc index 946dbc22fe0b12da71fc16c12726152db1df7f6e..62aa59a558aade07fe24610f9cc59ce4814a6b0a 100644 --- a/ui/ozone/common/native_pixmap_egl_binding.cc +++ b/ui/ozone/common/native_pixmap_egl_binding.cc @@ -49,6 +49,20 @@ unsigned GLInternalFormat(gfx::BufferFormat format) { return gl::BufferFormatToGLInternalFormat(format); } +#if BUILDFLAG(IS_OHOS) +#define EGL_NATIVE_BUFFER_OHOS 0x34E1 + +gl::ScopedEGLImage CreateOhosEGLImage(EGLClientBuffer egl_client_buffer) { + EGLint attrs[] = { + EGL_IMAGE_PRESERVED, + EGL_TRUE, + EGL_NONE, + }; + + return gl::MakeScopedEGLImage(EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_OHOS, + egl_client_buffer, attrs); +} +#else EGLint FourCC(gfx::BufferFormat format) { switch (format) { case gfx::BufferFormat::R_8: @@ -88,6 +102,7 @@ EGLint FourCC(gfx::BufferFormat format) { NOTREACHED(); return 0; } +#endif // Map buffer format to GL type. Return GL_NONE if no sensible mapping. unsigned BufferFormatToGLDataType(gfx::BufferFormat format) { @@ -161,6 +176,10 @@ bool NativePixmapEGLBinding::InitializeFromNativePixmap( GLenum target, GLuint texture_id) { DCHECK(!pixmap_); +#if BUILDFLAG(IS_OHOS) + LOG(DEBUG) << "[HeifSupport] InitializeFromNativePixmap GLInternalFormat " << (int)GLInternalFormat(format_) + << ", format_ " << (int)format_ << ", plane_ " << (int)plane_ << ", WindowBuffer " << pixmap->GetWindowBuffer(); +#endif if (GLInternalFormat(format_) == GL_NONE) { LOG(ERROR) << "Unsupported format: " << gfx::BufferFormatToString(format_); return false; @@ -171,6 +190,13 @@ bool NativePixmapEGLBinding::InitializeFromNativePixmap( return false; } +#if BUILDFLAG(IS_OHOS) + egl_image_ = CreateOhosEGLImage(static_cast(pixmap->GetWindowBuffer())); + if (egl_image_ == EGL_NO_IMAGE_KHR) { + LOG(ERROR) << "[HeifSupport] egl_image_ is EGL_NO_IMAGE_KHR."; + return false; + } +#else // Note: If eglCreateImageKHR is successful for a EGL_LINUX_DMA_BUF_EXT // target, the EGL will take a reference to the dma_buf. std::vector attrs; @@ -263,6 +289,7 @@ bool NativePixmapEGLBinding::InitializeFromNativePixmap( egl_image_ = gl::MakeScopedEGLImage(EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, static_cast(nullptr), &attrs[0]); +#endif if (!egl_image_.get()) { return false; } diff --git a/ui/ozone/platform/headless/headless_surface_factory.cc b/ui/ozone/platform/headless/headless_surface_factory.cc index 890742144b28ce2456759d5bf66bacaaefd0136c..37333b80c57fd71e3f7a0d20929b12b5f6a8727b 100644 --- a/ui/ozone/platform/headless/headless_surface_factory.cc +++ b/ui/ozone/platform/headless/headless_surface_factory.cc @@ -38,6 +38,11 @@ #include "ui/ozone/platform/headless/vulkan_implementation_headless.h" #endif +#if BUILDFLAG(IS_OHOS) +#include "ui/gfx/linux/native_pixmap_dmabuf.h" +#include "ui/ozone/common/native_pixmap_egl_binding.h" +#endif + namespace ui { namespace { @@ -187,6 +192,23 @@ class GLOzoneEGLHeadless : public GLOzoneEGL { ~GLOzoneEGLHeadless() override = default; // GLOzone: +#if BUILDFLAG(IS_OHOS) + bool CanImportNativePixmap() override { + return true; + } + + std::unique_ptr ImportNativePixmap( + scoped_refptr pixmap, + gfx::BufferFormat plane_format, + gfx::BufferPlane plane, + gfx::Size plane_size, + const gfx::ColorSpace& color_space, + GLenum target, + GLuint texture_id) override { + return NativePixmapEGLBinding::Create(pixmap, plane_format, plane, plane_size, + color_space, target, texture_id); + } +#endif scoped_refptr CreateViewGLSurface( gl::GLDisplay* display, gfx::AcceleratedWidget window) override { @@ -264,6 +286,21 @@ scoped_refptr HeadlessSurfaceFactory::CreateNativePixmap( return new TestPixmap(format); } +#if BUILDFLAG(IS_OHOS) +scoped_refptr HeadlessSurfaceFactory::CreateNativePixmapFromHandle( + gfx::AcceleratedWidget widget, + gfx::Size size, + gfx::BufferFormat format, + gfx::NativePixmapHandle handle, + void* window_buffer) { + scoped_refptr pixmap = + base::MakeRefCounted( + size, format, std::move(handle), window_buffer); + + return pixmap; +} +#endif + void HeadlessSurfaceFactory::CheckBasePath() const { if (base_path_.empty()) return; diff --git a/ui/ozone/platform/headless/headless_surface_factory.h b/ui/ozone/platform/headless/headless_surface_factory.h index f50c27ad9941faf5cd6e8f3c0ebf342d53bef084..e088d9f56186e9a3f5bf04d4a5c69366d204f1ec 100644 --- a/ui/ozone/platform/headless/headless_surface_factory.h +++ b/ui/ozone/platform/headless/headless_surface_factory.h @@ -40,6 +40,14 @@ class HeadlessSurfaceFactory : public SurfaceFactoryOzone { gfx::BufferFormat format, gfx::BufferUsage usage, absl::optional framebuffer_size = absl::nullopt) override; +#if BUILDFLAG(IS_OHOS) + scoped_refptr CreateNativePixmapFromHandle( + gfx::AcceleratedWidget widget, + gfx::Size size, + gfx::BufferFormat format, + gfx::NativePixmapHandle handle, + void* window_buffer) override; +#endif private: void CheckBasePath() const; diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h index f61ffe943680896432cad35d849e6a0ae5042d42..a29259b76cb7b6eda9f902eeb1590c65c7df95de 100644 --- a/ui/ozone/public/ozone_platform.h +++ b/ui/ozone/public/ozone_platform.h @@ -182,7 +182,11 @@ class COMPONENT_EXPORT(OZONE) OzonePlatform { bool supports_non_backed_solid_color_buffers = false; // Indicates whether the platform supports native pixmaps. +#if BUILDFLAG(IS_OHOS) + bool supports_native_pixmaps = true; +#else bool supports_native_pixmaps = false; +#endif // Wayland only: determines whether BufferQueue needs a background image to // be stacked below an AcceleratedWidget to make a widget opaque. diff --git a/ui/ozone/public/surface_factory_ozone.cc b/ui/ozone/public/surface_factory_ozone.cc index b29f161524b5075d71d8a26f24fbb2653597a459..3a2afc08e1a481bad7266505cf2e83ebdc639720 100644 --- a/ui/ozone/public/surface_factory_ozone.cc +++ b/ui/ozone/public/surface_factory_ozone.cc @@ -108,7 +108,12 @@ SurfaceFactoryOzone::CreateNativePixmapFromHandle( gfx::AcceleratedWidget widget, gfx::Size size, gfx::BufferFormat format, - gfx::NativePixmapHandle handle) { +#if BUILDFLAG(IS_OHOS) + gfx::NativePixmapHandle handle, + void* window_buffer) { +#else + gfx::NativePixmapHandle handle) { +#endif return nullptr; } diff --git a/ui/ozone/public/surface_factory_ozone.h b/ui/ozone/public/surface_factory_ozone.h index f163fb070da8dbf262e5f6926d39c40d51c6ad45..a41a8f29465884f8dc69eb206a854d2a8bec0453 100644 --- a/ui/ozone/public/surface_factory_ozone.h +++ b/ui/ozone/public/surface_factory_ozone.h @@ -168,7 +168,12 @@ class COMPONENT_EXPORT(OZONE_BASE) SurfaceFactoryOzone { gfx::AcceleratedWidget widget, gfx::Size size, gfx::BufferFormat format, +#if BUILDFLAG(IS_OHOS) + gfx::NativePixmapHandle handle, + void* window_buffer = nullptr); +#else gfx::NativePixmapHandle handle); +#endif // A temporary solution that allows protected NativePixmap management to be // handled outside the Ozone platform (crbug.com/771863).