Home | History | Annotate | Download | only in skia
      1 /*
      2  * Copyright (C) 2016 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 "SkiaVulkanPipeline.h"
     18 
     19 #include "DeferredLayerUpdater.h"
     20 #include "Readback.h"
     21 #include "ShaderCache.h"
     22 #include "SkiaPipeline.h"
     23 #include "SkiaProfileRenderer.h"
     24 #include "VkInteropFunctorDrawable.h"
     25 #include "renderstate/RenderState.h"
     26 #include "renderthread/Frame.h"
     27 
     28 #include <SkSurface.h>
     29 #include <SkTypes.h>
     30 
     31 #include <GrContext.h>
     32 #include <GrTypes.h>
     33 #include <vk/GrVkTypes.h>
     34 
     35 #include <cutils/properties.h>
     36 #include <strings.h>
     37 
     38 using namespace android::uirenderer::renderthread;
     39 
     40 namespace android {
     41 namespace uirenderer {
     42 namespace skiapipeline {
     43 
     44 SkiaVulkanPipeline::SkiaVulkanPipeline(renderthread::RenderThread& thread)
     45         : SkiaPipeline(thread), mVkManager(thread.vulkanManager()) {
     46     thread.renderState().registerContextCallback(this);
     47 }
     48 
     49 SkiaVulkanPipeline::~SkiaVulkanPipeline() {
     50     mRenderThread.renderState().removeContextCallback(this);
     51 }
     52 
     53 MakeCurrentResult SkiaVulkanPipeline::makeCurrent() {
     54     return MakeCurrentResult::AlreadyCurrent;
     55 }
     56 
     57 Frame SkiaVulkanPipeline::getFrame() {
     58     LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr, "getFrame() called on a context with no surface!");
     59     return mVkManager.dequeueNextBuffer(mVkSurface);
     60 }
     61 
     62 bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty,
     63                               const LightGeometry& lightGeometry,
     64                               LayerUpdateQueue* layerUpdateQueue, const Rect& contentDrawBounds,
     65                               bool opaque, const LightInfo& lightInfo,
     66                               const std::vector<sp<RenderNode>>& renderNodes,
     67                               FrameInfoVisualizer* profiler) {
     68     sk_sp<SkSurface> backBuffer = mVkSurface->getCurrentSkSurface();
     69     if (backBuffer.get() == nullptr) {
     70         return false;
     71     }
     72     SkiaPipeline::updateLighting(lightGeometry, lightInfo);
     73     renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, backBuffer,
     74                 mVkSurface->getCurrentPreTransform());
     75     ShaderCache::get().onVkFrameFlushed(mRenderThread.getGrContext());
     76     layerUpdateQueue->clear();
     77 
     78     // Draw visual debugging features
     79     if (CC_UNLIKELY(Properties::showDirtyRegions ||
     80                     ProfileType::None != Properties::getProfileType())) {
     81         SkCanvas* profileCanvas = backBuffer->getCanvas();
     82         SkiaProfileRenderer profileRenderer(profileCanvas);
     83         profiler->draw(profileRenderer);
     84         profileCanvas->flush();
     85     }
     86 
     87     // Log memory statistics
     88     if (CC_UNLIKELY(Properties::debugLevel != kDebugDisabled)) {
     89         dumpResourceCacheUsage();
     90     }
     91 
     92     return true;
     93 }
     94 
     95 bool SkiaVulkanPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty,
     96                                      FrameInfo* currentFrameInfo, bool* requireSwap) {
     97     *requireSwap = drew;
     98 
     99     // Even if we decided to cancel the frame, from the perspective of jank
    100     // metrics the frame was swapped at this point
    101     currentFrameInfo->markSwapBuffers();
    102 
    103     if (*requireSwap) {
    104         mVkManager.swapBuffers(mVkSurface, screenDirty);
    105     }
    106 
    107     return *requireSwap;
    108 }
    109 
    110 DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() {
    111     mRenderThread.requireVkContext();
    112 
    113     return new DeferredLayerUpdater(mRenderThread.renderState());
    114 }
    115 
    116 void SkiaVulkanPipeline::onStop() {}
    117 
    118 bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior swapBehavior,
    119                                     ColorMode colorMode, uint32_t extraBuffers) {
    120     if (mVkSurface) {
    121         mVkManager.destroySurface(mVkSurface);
    122         mVkSurface = nullptr;
    123     }
    124 
    125     setSurfaceColorProperties(colorMode);
    126     if (surface) {
    127         mRenderThread.requireVkContext();
    128         mVkSurface =
    129                 mVkManager.createSurface(surface, colorMode, mSurfaceColorSpace, mSurfaceColorType,
    130                                          mRenderThread.getGrContext(), extraBuffers);
    131     }
    132 
    133     return mVkSurface != nullptr;
    134 }
    135 
    136 bool SkiaVulkanPipeline::isSurfaceReady() {
    137     return CC_UNLIKELY(mVkSurface != nullptr);
    138 }
    139 
    140 bool SkiaVulkanPipeline::isContextReady() {
    141     return CC_LIKELY(mVkManager.hasVkContext());
    142 }
    143 
    144 void SkiaVulkanPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) {
    145     VkInteropFunctorDrawable::vkInvokeFunctor(functor);
    146 }
    147 
    148 sk_sp<Bitmap> SkiaVulkanPipeline::allocateHardwareBitmap(renderthread::RenderThread& renderThread,
    149                                                          SkBitmap& skBitmap) {
    150     LOG_ALWAYS_FATAL("Unimplemented");
    151     return nullptr;
    152 }
    153 
    154 void SkiaVulkanPipeline::onContextDestroyed() {
    155     if (mVkSurface) {
    156         mVkManager.destroySurface(mVkSurface);
    157         mVkSurface = nullptr;
    158     }
    159 }
    160 
    161 } /* namespace skiapipeline */
    162 } /* namespace uirenderer */
    163 } /* namespace android */
    164