// Copyright 2017 The Chromium 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/android/android_surface_software.h" #include "flutter/common/threads.h" #include "flutter/fml/platform/android/jni_weak_ref.h" #include "flutter/fml/platform/android/scoped_java_ref.h" #include "flutter/shell/platform/android/platform_view_android_jni.h" #include #include #include "flutter/fml/trace_event.h" #include "lib/fxl/logging.h" namespace shell { namespace { bool GetSkColorType(int32_t buffer_format, SkColorType* color_type, SkAlphaType* alpha_type) { switch (buffer_format) { case WINDOW_FORMAT_RGB_565: *color_type = kRGB_565_SkColorType; *alpha_type = kOpaque_SkAlphaType; return true; case WINDOW_FORMAT_RGBA_8888: *color_type = kRGBA_8888_SkColorType; *alpha_type = kPremul_SkAlphaType; return true; default: return false; } } } // anonymous namespace AndroidSurfaceSoftware::AndroidSurfaceSoftware() { GetSkColorType(WINDOW_FORMAT_RGBA_8888, &target_color_type_, &target_alpha_type_); } AndroidSurfaceSoftware::~AndroidSurfaceSoftware() = default; bool AndroidSurfaceSoftware::IsValid() const { return true; } bool AndroidSurfaceSoftware::ResourceContextMakeCurrent() { // Resource Context always not available on software backend. return false; } std::unique_ptr AndroidSurfaceSoftware::CreateGPUSurface() { if (!IsValid()) { return nullptr; } auto surface = std::make_unique(this); if (!surface->IsValid()) { return nullptr; } return surface; } sk_sp AndroidSurfaceSoftware::AcquireBackingStore( const SkISize& size) { TRACE_EVENT0("flutter", "AndroidSurfaceSoftware::AcquireBackingStore"); if (!IsValid()) { 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 image_info = SkImageInfo::Make( size.fWidth, size.fHeight, target_color_type_, target_alpha_type_); sk_surface_ = SkSurface::MakeRaster(image_info); return sk_surface_; } bool AndroidSurfaceSoftware::PresentBackingStore( sk_sp backing_store) { TRACE_EVENT0("flutter", "AndroidSurfaceSoftware::PresentBackingStore"); if (!IsValid() || backing_store == nullptr) { return false; } SkPixmap pixmap; if (!backing_store->peekPixels(&pixmap)) { return false; } ANativeWindow_Buffer native_buffer; if (ANativeWindow_lock(native_window_->handle(), &native_buffer, nullptr)) { return false; } SkColorType color_type; SkAlphaType alpha_type; if (GetSkColorType(native_buffer.format, &color_type, &alpha_type)) { SkImageInfo native_image_info = SkImageInfo::Make( native_buffer.width, native_buffer.height, color_type, alpha_type); std::unique_ptr canvas = SkCanvas::MakeRasterDirect( native_image_info, native_buffer.bits, native_buffer.stride * SkColorTypeBytesPerPixel(color_type)); if (canvas) { SkBitmap bitmap; if (bitmap.installPixels(pixmap)) { canvas->drawBitmapRect( bitmap, SkRect::MakeIWH(native_buffer.width, native_buffer.height), nullptr); } } } ANativeWindow_unlockAndPost(native_window_->handle()); return true; } void AndroidSurfaceSoftware::TeardownOnScreenContext() {} SkISize AndroidSurfaceSoftware::OnScreenSurfaceSize() const { return SkISize(); } bool AndroidSurfaceSoftware::OnScreenSurfaceResize(const SkISize& size) const { return true; } bool AndroidSurfaceSoftware::SetNativeWindow( fxl::RefPtr window, PlatformView::SurfaceConfig config) { native_window_ = std::move(window); if (!(native_window_ && native_window_->IsValid())) return false; int32_t window_format = ANativeWindow_getFormat(native_window_->handle()); if (window_format < 0) return false; if (!GetSkColorType(window_format, &target_color_type_, &target_alpha_type_)) return false; return true; } } // namespace shell