DrawFrameTask.cpp revision f9be77940e365036fecd8cc0e491e8545c34e79b
1/* 2 * Copyright (C) 2014 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#define ATRACE_TAG ATRACE_TAG_VIEW 18 19#include "DrawFrameTask.h" 20 21#include <utils/Log.h> 22#include <utils/Trace.h> 23 24#include "../DisplayList.h" 25#include "../RenderNode.h" 26#include "CanvasContext.h" 27#include "RenderThread.h" 28 29namespace android { 30namespace uirenderer { 31namespace renderthread { 32 33DrawFrameTask::DrawFrameTask() 34 : mRenderThread(NULL) 35 , mContext(NULL) 36 , mFrameTimeNanos(0) 37 , mSyncResult(kSync_OK) { 38} 39 40DrawFrameTask::~DrawFrameTask() { 41} 42 43void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context) { 44 mRenderThread = thread; 45 mContext = context; 46} 47 48void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) { 49 LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to addLayer with!"); 50 51 mLayers.push(layer); 52} 53 54void DrawFrameTask::removeLayer(DeferredLayerUpdater* layer) { 55 for (size_t i = 0; i < mLayers.size(); i++) { 56 if (mLayers[i] == layer) { 57 mLayers.removeAt(i); 58 break; 59 } 60 } 61} 62 63void DrawFrameTask::setDirty(int left, int top, int right, int bottom) { 64 mDirty.set(left, top, right, bottom); 65} 66 67int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos) { 68 LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!"); 69 70 mSyncResult = kSync_OK; 71 mFrameTimeNanos = frameTimeNanos; 72 postAndWait(); 73 74 // Reset the single-frame data 75 mFrameTimeNanos = 0; 76 mDirty.setEmpty(); 77 78 return mSyncResult; 79} 80 81void DrawFrameTask::postAndWait() { 82 AutoMutex _lock(mLock); 83 mRenderThread->queue(this); 84 mSignal.wait(mLock); 85} 86 87void DrawFrameTask::run() { 88 ATRACE_NAME("DrawFrame"); 89 90 bool canUnblockUiThread = syncFrameState(); 91 92 // Grab a copy of everything we need 93 Rect dirty(mDirty); 94 CanvasContext* context = mContext; 95 96 // From this point on anything in "this" is *UNSAFE TO ACCESS* 97 if (canUnblockUiThread) { 98 unblockUiThread(); 99 } 100 101 context->draw(&dirty); 102 103 if (!canUnblockUiThread) { 104 unblockUiThread(); 105 } 106} 107 108static void initTreeInfo(TreeInfo& info) { 109 info.prepareTextures = true; 110 info.performStagingPush = true; 111 info.evaluateAnimations = true; 112} 113 114bool DrawFrameTask::syncFrameState() { 115 ATRACE_CALL(); 116 mRenderThread->timeLord().vsyncReceived(mFrameTimeNanos); 117 mContext->makeCurrent(); 118 Caches::getInstance().textureCache.resetMarkInUse(); 119 TreeInfo info; 120 initTreeInfo(info); 121 mContext->prepareDraw(&mLayers, info); 122 if (info.out.hasAnimations) { 123 // TODO: dirty calculations, for now just do a full-screen inval 124 mDirty.setEmpty(); 125 if (info.out.requiresUiRedraw) { 126 mSyncResult |= kSync_UIRedrawRequired; 127 } 128 } 129 // If prepareTextures is false, we ran out of texture cache space 130 return !info.out.hasFunctors && info.prepareTextures; 131} 132 133void DrawFrameTask::unblockUiThread() { 134 AutoMutex _lock(mLock); 135 mSignal.signal(); 136} 137 138} /* namespace renderthread */ 139} /* namespace uirenderer */ 140} /* namespace android */ 141