Home | History | Annotate | Download | only in skia
      1 /*
      2  * Copyright (C) 2018 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include "VkFunctorDrawable.h"
     18 #include <private/hwui/DrawVkInfo.h>
     19 
     20 #include <GrBackendDrawableInfo.h>
     21 #include <SkAndroidFrameworkUtils.h>
     22 #include <SkImage.h>
     23 #include <utils/Color.h>
     24 #include <utils/Trace.h>
     25 #include <utils/TraceUtils.h>
     26 #include <vk/GrVkTypes.h>
     27 #include <thread>
     28 #include "renderthread/RenderThread.h"
     29 #include "renderthread/VulkanManager.h"
     30 #include "thread/ThreadBase.h"
     31 #include "utils/TimeUtils.h"
     32 
     33 namespace android {
     34 namespace uirenderer {
     35 namespace skiapipeline {
     36 
     37 VkFunctorDrawHandler::VkFunctorDrawHandler(sp<WebViewFunctor::Handle> functor_handle,
     38                                            const SkMatrix& matrix, const SkIRect& clip,
     39                                            const SkImageInfo& image_info)
     40         : INHERITED()
     41         , mFunctorHandle(functor_handle)
     42         , mMatrix(matrix)
     43         , mClip(clip)
     44         , mImageInfo(image_info) {}
     45 
     46 VkFunctorDrawHandler::~VkFunctorDrawHandler() {
     47     if (mDrawn) {
     48         mFunctorHandle->postDrawVk();
     49     }
     50 }
     51 
     52 void VkFunctorDrawHandler::draw(const GrBackendDrawableInfo& info) {
     53     ATRACE_CALL();
     54     if (!renderthread::RenderThread::isCurrent())
     55         LOG_ALWAYS_FATAL("VkFunctorDrawHandler::draw not called on render thread");
     56 
     57     GrVkDrawableInfo vulkan_info;
     58     if (!info.getVkDrawableInfo(&vulkan_info)) {
     59         return;
     60     }
     61     renderthread::VulkanManager& vk_manager =
     62             renderthread::RenderThread::getInstance().vulkanManager();
     63     mFunctorHandle->initVk(vk_manager.getVkFunctorInitParams());
     64 
     65     SkMatrix44 mat4(mMatrix);
     66     VkFunctorDrawParams params{
     67             .width = mImageInfo.width(),
     68             .height = mImageInfo.height(),
     69             .color_space_ptr = mImageInfo.colorSpace(),
     70             .clip_left = mClip.fLeft,
     71             .clip_top = mClip.fTop,
     72             .clip_right = mClip.fRight,
     73             .clip_bottom = mClip.fBottom,
     74     };
     75     mat4.asColMajorf(&params.transform[0]);
     76     params.secondary_command_buffer = vulkan_info.fSecondaryCommandBuffer;
     77     params.color_attachment_index = vulkan_info.fColorAttachmentIndex;
     78     params.compatible_render_pass = vulkan_info.fCompatibleRenderPass;
     79     params.format = vulkan_info.fFormat;
     80 
     81     mFunctorHandle->drawVk(params);
     82     mDrawn = true;
     83 
     84     vulkan_info.fDrawBounds->offset.x = mClip.fLeft;
     85     vulkan_info.fDrawBounds->offset.y = mClip.fTop;
     86     vulkan_info.fDrawBounds->extent.width = mClip.fRight - mClip.fLeft;
     87     vulkan_info.fDrawBounds->extent.height = mClip.fBottom - mClip.fTop;
     88 }
     89 
     90 VkFunctorDrawable::~VkFunctorDrawable() {}
     91 
     92 void VkFunctorDrawable::onDraw(SkCanvas* canvas) {
     93     // "canvas" is either SkNWayCanvas created by SkiaPipeline::tryCapture (SKP capture use case) or
     94     // AlphaFilterCanvas (used by RenderNodeDrawable to apply alpha in certain cases).
     95     // "VkFunctorDrawable::onDraw" is not invoked for the most common case, when drawing in a GPU
     96     // canvas.
     97 
     98     if (canvas->getGrContext() == nullptr) {
     99         // We're dumping a picture, render a light-blue rectangle instead
    100         SkPaint paint;
    101         paint.setColor(0xFF81D4FA);
    102         canvas->drawRect(mBounds, paint);
    103     } else {
    104         // Handle the case when "canvas" is AlphaFilterCanvas. Find the wrapped GPU canvas.
    105         SkCanvas* gpuCanvas = SkAndroidFrameworkUtils::getBaseWrappedCanvas(canvas);
    106         // Enforce "canvas" must be an AlphaFilterCanvas. For GPU canvas, the call should come from
    107         // onSnapGpuDrawHandler.
    108         LOG_ALWAYS_FATAL_IF(gpuCanvas == canvas,
    109                             "VkFunctorDrawable::onDraw() should not be called with a GPU canvas!");
    110 
    111         // This will invoke onSnapGpuDrawHandler and regular draw flow.
    112         gpuCanvas->drawDrawable(this);
    113     }
    114 }
    115 
    116 std::unique_ptr<FunctorDrawable::GpuDrawHandler> VkFunctorDrawable::onSnapGpuDrawHandler(
    117         GrBackendApi backendApi, const SkMatrix& matrix, const SkIRect& clip,
    118         const SkImageInfo& image_info) {
    119     if (backendApi != GrBackendApi::kVulkan) {
    120         return nullptr;
    121     }
    122     std::unique_ptr<VkFunctorDrawHandler> draw;
    123     if (mAnyFunctor.index() == 0) {
    124         return std::make_unique<VkFunctorDrawHandler>(std::get<0>(mAnyFunctor).handle, matrix, clip,
    125                                                       image_info);
    126     } else {
    127         LOG_ALWAYS_FATAL("Not implemented");
    128     }
    129 }
    130 
    131 }  // namespace skiapipeline
    132 }  // namespace uirenderer
    133 }  // namespace android
    134