| // 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/shell/platform/embedder/embedder_surface_software.h" |
| |
| #include "flutter/fml/trace_event.h" |
| #include "third_party/skia/include/core/SkColorSpace.h" |
| #include "third_party/skia/include/core/SkImageInfo.h" |
| #include "third_party/skia/include/gpu/GrDirectContext.h" |
| |
| namespace flutter { |
| |
| EmbedderSurfaceSoftware::EmbedderSurfaceSoftware( |
| SoftwareDispatchTable software_dispatch_table, |
| std::shared_ptr<EmbedderExternalViewEmbedder> external_view_embedder) |
| : software_dispatch_table_(software_dispatch_table), |
| external_view_embedder_(external_view_embedder) { |
| if (!software_dispatch_table_.software_present_backing_store) { |
| return; |
| } |
| valid_ = true; |
| } |
| |
| EmbedderSurfaceSoftware::~EmbedderSurfaceSoftware() = default; |
| |
| // |EmbedderSurface| |
| bool EmbedderSurfaceSoftware::IsValid() const { |
| return valid_; |
| } |
| |
| // |EmbedderSurface| |
| std::unique_ptr<Surface> EmbedderSurfaceSoftware::CreateGPUSurface() { |
| if (!IsValid()) { |
| return nullptr; |
| } |
| const bool render_to_surface = !external_view_embedder_; |
| auto surface = std::make_unique<GPUSurfaceSoftware>(this, render_to_surface); |
| |
| if (!surface->IsValid()) { |
| return nullptr; |
| } |
| |
| return surface; |
| } |
| |
| // |EmbedderSurface| |
| sk_sp<GrDirectContext> EmbedderSurfaceSoftware::CreateResourceContext() const { |
| return nullptr; |
| } |
| |
| // |GPUSurfaceSoftwareDelegate| |
| sk_sp<SkSurface> EmbedderSurfaceSoftware::AcquireBackingStore( |
| const SkISize& size) { |
| TRACE_EVENT0("flutter", "EmbedderSurfaceSoftware::AcquireBackingStore"); |
| if (!IsValid()) { |
| FML_LOG(ERROR) |
| << "Could not acquire backing store for the software surface."; |
| return nullptr; |
| } |
| |
| if (sk_surface_ != nullptr && |
| SkISize::Make(sk_surface_->width(), sk_surface_->height()) == size) { |
| // The old and new surface sizes are the same. Nothing to do here. |
| return sk_surface_; |
| } |
| |
| SkImageInfo info = SkImageInfo::MakeN32( |
| size.fWidth, size.fHeight, kPremul_SkAlphaType, SkColorSpace::MakeSRGB()); |
| sk_surface_ = SkSurface::MakeRaster(info, nullptr); |
| |
| if (sk_surface_ == nullptr) { |
| FML_LOG(ERROR) << "Could not create backing store for software rendering."; |
| return nullptr; |
| } |
| |
| return sk_surface_; |
| } |
| |
| // |GPUSurfaceSoftwareDelegate| |
| bool EmbedderSurfaceSoftware::PresentBackingStore( |
| sk_sp<SkSurface> backing_store) { |
| if (!IsValid()) { |
| FML_LOG(ERROR) << "Tried to present an invalid software surface."; |
| return false; |
| } |
| |
| SkPixmap pixmap; |
| if (!backing_store->peekPixels(&pixmap)) { |
| FML_LOG(ERROR) << "Could not peek the pixels of the backing store."; |
| return false; |
| } |
| |
| // Some basic sanity checking. |
| uint64_t expected_pixmap_data_size = pixmap.width() * pixmap.height() * 4; |
| |
| const size_t pixmap_size = pixmap.computeByteSize(); |
| |
| if (expected_pixmap_data_size != pixmap_size) { |
| FML_LOG(ERROR) << "Software backing store had unexpected size."; |
| return false; |
| } |
| |
| return software_dispatch_table_.software_present_backing_store( |
| pixmap.addr(), // |
| pixmap.rowBytes(), // |
| pixmap.height() // |
| ); |
| } |
| |
| } // namespace flutter |