SkiaVulkanPipeline.cpp revision 500a0c30d4dcd012218c3e44a62926a1c34a259f
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 "renderthread/EglManager.h" // needed for Frame 21#include "Readback.h" 22#include "renderstate/RenderState.h" 23 24#include <SkTypes.h> 25#include <WindowContextFactory_android.h> 26#include <VulkanWindowContext.h> 27 28#include <android/native_window.h> 29#include <cutils/properties.h> 30#include <strings.h> 31 32using namespace android::uirenderer::renderthread; 33using namespace sk_app; 34 35namespace android { 36namespace uirenderer { 37namespace skiapipeline { 38 39MakeCurrentResult SkiaVulkanPipeline::makeCurrent() { 40 return (mWindowContext != nullptr) ? 41 MakeCurrentResult::AlreadyCurrent : MakeCurrentResult::Failed; 42} 43 44Frame SkiaVulkanPipeline::getFrame() { 45 LOG_ALWAYS_FATAL_IF(mWindowContext == nullptr, "Tried to draw into null vulkan context!"); 46 mBackbuffer = mWindowContext->getBackbufferSurface(); 47 if (mBackbuffer.get() == nullptr) { 48 // try recreating the context? 49 SkDebugf("failed to get backbuffer"); 50 return Frame(-1, -1, 0); 51 } 52 53 // TODO: support buffer age if Vulkan API can do it 54 Frame frame(mBackbuffer->width(), mBackbuffer->height(), 0); 55 return frame; 56} 57 58bool SkiaVulkanPipeline::draw(const Frame& frame, const SkRect& screenDirty, 59 const SkRect& dirty, 60 const FrameBuilder::LightGeometry& lightGeometry, 61 LayerUpdateQueue* layerUpdateQueue, 62 const Rect& contentDrawBounds, bool opaque, 63 const BakedOpRenderer::LightInfo& lightInfo, 64 const std::vector<sp<RenderNode>>& renderNodes, 65 FrameInfoVisualizer* profiler) { 66 67 if (mBackbuffer.get() == nullptr) { 68 return false; 69 } 70 renderFrame(*layerUpdateQueue, dirty, renderNodes, opaque, contentDrawBounds, mBackbuffer); 71 layerUpdateQueue->clear(); 72 return true; 73} 74 75bool SkiaVulkanPipeline::swapBuffers(const Frame& frame, bool drew, 76 const SkRect& screenDirty, FrameInfo* currentFrameInfo, bool* requireSwap) { 77 78 *requireSwap = drew; 79 80 // Even if we decided to cancel the frame, from the perspective of jank 81 // metrics the frame was swapped at this point 82 currentFrameInfo->markSwapBuffers(); 83 84 if (*requireSwap) { 85 mWindowContext->swapBuffers(); 86 } 87 88 mBackbuffer.reset(); 89 90 return *requireSwap; 91} 92 93bool SkiaVulkanPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { 94 // TODO: implement copyLayerInto for vulkan. 95 return false; 96} 97 98DeferredLayerUpdater* SkiaVulkanPipeline::createTextureLayer() { 99 Layer* layer = new Layer(mRenderThread.renderState(), 0, 0); 100 return new DeferredLayerUpdater(layer); 101} 102 103void SkiaVulkanPipeline::onStop() { 104} 105 106bool SkiaVulkanPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior) { 107 108 if (mWindowContext) { 109 delete mWindowContext; 110 mWindowContext = nullptr; 111 } 112 113 if (surface) { 114 DisplayParams displayParams; 115 mWindowContext = window_context_factory::NewVulkanForAndroid(surface, displayParams); 116 if (mWindowContext) { 117 DeviceInfo::initialize(mWindowContext->getGrContext()->caps()->maxRenderTargetSize()); 118 } 119 } 120 121 122 // this doesn't work for if there is more than one CanvasContext available at one time! 123 mRenderThread.setGrContext(mWindowContext ? mWindowContext->getGrContext() : nullptr); 124 125 return mWindowContext != nullptr; 126} 127 128bool SkiaVulkanPipeline::isSurfaceReady() { 129 return CC_LIKELY(mWindowContext != nullptr) && mWindowContext->isValid(); 130} 131 132bool SkiaVulkanPipeline::isContextReady() { 133 return CC_LIKELY(mWindowContext != nullptr); 134} 135 136void SkiaVulkanPipeline::invokeFunctor(const RenderThread& thread, Functor* functor) { 137 // TODO: we currently don't support OpenGL WebView's 138 DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext; 139 (*functor)(mode, nullptr); 140} 141 142} /* namespace skiapipeline */ 143} /* namespace uirenderer */ 144} /* namespace android */ 145