OpenGLPipeline.cpp revision 56ad6ec42f814e9e61030ff819cac4e5d31def8b
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 "OpenGLPipeline.h" 18 19#include "DeferredLayerUpdater.h" 20#include "EglManager.h" 21#include "renderstate/RenderState.h" 22#include "Readback.h" 23 24#include <android/native_window.h> 25#include <cutils/properties.h> 26#include <strings.h> 27 28namespace android { 29namespace uirenderer { 30namespace renderthread { 31 32OpenGLPipeline::OpenGLPipeline(RenderThread& thread) 33 : mEglManager(thread.eglManager()), mRenderThread(thread) { 34} 35 36MakeCurrentResult OpenGLPipeline::makeCurrent() { 37 // TODO: Figure out why this workaround is needed, see b/13913604 38 // In the meantime this matches the behavior of GLRenderer, so it is not a regression 39 EGLint error = 0; 40 bool haveNewSurface = mEglManager.makeCurrent(mEglSurface, &error); 41 42 Caches::getInstance().textureCache.resetMarkInUse(this); 43 if (!haveNewSurface) { 44 return MakeCurrentResult::AlreadyCurrent; 45 } 46 return error ? MakeCurrentResult::Failed : MakeCurrentResult::Succeeded; 47} 48 49Frame OpenGLPipeline::getFrame() { 50 LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE, 51 "drawRenderNode called on a context with no surface!"); 52 return mEglManager.beginFrame(mEglSurface); 53} 54 55bool OpenGLPipeline::draw(const Frame& frame, const SkRect& screenDirty, const SkRect& dirty, 56 const FrameBuilder::LightGeometry& lightGeometry, 57 LayerUpdateQueue* layerUpdateQueue, 58 const Rect& contentDrawBounds, bool opaque, 59 const BakedOpRenderer::LightInfo& lightInfo, 60 const std::vector< sp<RenderNode> >& renderNodes, 61 FrameInfoVisualizer* profiler) { 62 63 mEglManager.damageFrame(frame, dirty); 64 65 bool drew = false; 66 67 68 auto& caches = Caches::getInstance(); 69 FrameBuilder frameBuilder(dirty, frame.width(), frame.height(), lightGeometry, caches); 70 71 frameBuilder.deferLayers(*layerUpdateQueue); 72 layerUpdateQueue->clear(); 73 74 frameBuilder.deferRenderNodeScene(renderNodes, contentDrawBounds); 75 76 BakedOpRenderer renderer(caches, mRenderThread.renderState(), 77 opaque, lightInfo); 78 frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); 79 profiler->draw(&renderer); 80 drew = renderer.didDraw(); 81 82 // post frame cleanup 83 caches.clearGarbage(); 84 caches.pathCache.trim(); 85 caches.tessellationCache.trim(); 86 87#if DEBUG_MEMORY_USAGE 88 mCaches.dumpMemoryUsage(); 89#else 90 if (CC_UNLIKELY(Properties::debugLevel & kDebugMemory)) { 91 caches.dumpMemoryUsage(); 92 } 93#endif 94 95 return drew; 96} 97 98bool OpenGLPipeline::swapBuffers(const Frame& frame, bool drew, const SkRect& screenDirty, 99 FrameInfo* currentFrameInfo, bool* requireSwap) { 100 101 GL_CHECKPOINT(LOW); 102 103 // Even if we decided to cancel the frame, from the perspective of jank 104 // metrics the frame was swapped at this point 105 currentFrameInfo->markSwapBuffers(); 106 107 *requireSwap = drew || mEglManager.damageRequiresSwap(); 108 109 if (*requireSwap && (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty)))) { 110 return false; 111 } 112 113 return *requireSwap; 114} 115 116bool OpenGLPipeline::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { 117 layer->apply(); 118 return Readback::copyTextureLayerInto(mRenderThread, *(layer->backingLayer()), bitmap) 119 == CopyResult::Success; 120} 121 122DeferredLayerUpdater* OpenGLPipeline::createTextureLayer() { 123 mEglManager.initialize(); 124 Layer* layer = new Layer(mRenderThread.renderState(), 0, 0); 125 Caches::getInstance().textureState().activateTexture(0); 126 layer->generateTexture(); 127 128 return new DeferredLayerUpdater(layer); 129} 130 131void OpenGLPipeline::onStop() { 132 if (mEglManager.isCurrent(mEglSurface)) { 133 mEglManager.makeCurrent(EGL_NO_SURFACE); 134 } 135} 136 137bool OpenGLPipeline::setSurface(Surface* surface, SwapBehavior swapBehavior) { 138 139 if (mEglSurface != EGL_NO_SURFACE) { 140 mEglManager.destroySurface(mEglSurface); 141 mEglSurface = EGL_NO_SURFACE; 142 } 143 144 if (surface) { 145 mEglSurface = mEglManager.createSurface(surface); 146 } 147 148 if (mEglSurface != EGL_NO_SURFACE) { 149 const bool preserveBuffer = (swapBehavior != SwapBehavior::kSwap_discardBuffer); 150 mBufferPreserved = mEglManager.setPreserveBuffer(mEglSurface, preserveBuffer); 151 return true; 152 } 153 154 return false; 155} 156 157bool OpenGLPipeline::isSurfaceReady() { 158 return CC_UNLIKELY(mEglSurface != EGL_NO_SURFACE); 159} 160 161bool OpenGLPipeline::isContextReady() { 162 return CC_LIKELY(mEglManager.hasEglContext()); 163} 164 165void OpenGLPipeline::onDestroyHardwareResources() { 166 Caches& caches = Caches::getInstance(); 167 // Make sure to release all the textures we were owning as there won't 168 // be another draw 169 caches.textureCache.resetMarkInUse(this); 170 mRenderThread.renderState().flush(Caches::FlushMode::Layers); 171} 172 173void OpenGLPipeline::renderLayers(const FrameBuilder::LightGeometry& lightGeometry, 174 LayerUpdateQueue* layerUpdateQueue, bool opaque, 175 const BakedOpRenderer::LightInfo& lightInfo) { 176 static const std::vector< sp<RenderNode> > emptyNodeList; 177 auto& caches = Caches::getInstance(); 178 FrameBuilder frameBuilder(*layerUpdateQueue, lightGeometry, caches); 179 layerUpdateQueue->clear(); 180 BakedOpRenderer renderer(caches, mRenderThread.renderState(), 181 opaque, lightInfo); 182 LOG_ALWAYS_FATAL_IF(renderer.didDraw(), "shouldn't draw in buildlayer case"); 183 frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); 184} 185 186TaskManager* OpenGLPipeline::getTaskManager() { 187 return &Caches::getInstance().tasks; 188} 189 190} /* namespace renderthread */ 191} /* namespace uirenderer */ 192} /* namespace android */ 193