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 "../DeferredLayerUpdater.h" 25 #include "../DisplayList.h" 26 #include "../RenderNode.h" 27 #include "CanvasContext.h" 28 #include "RenderThread.h" 29 30 namespace android { 31 namespace uirenderer { 32 namespace renderthread { 33 34 DrawFrameTask::DrawFrameTask() 35 : mRenderThread(NULL) 36 , mContext(NULL) 37 , mFrameTimeNanos(0) 38 , mRecordDurationNanos(0) 39 , mDensity(1.0f) // safe enough default 40 , mSyncResult(kSync_OK) { 41 } 42 43 DrawFrameTask::~DrawFrameTask() { 44 } 45 46 void DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context) { 47 mRenderThread = thread; 48 mContext = context; 49 } 50 51 void DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) { 52 LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to pushLayerUpdate with!"); 53 54 for (size_t i = 0; i < mLayers.size(); i++) { 55 if (mLayers[i].get() == layer) { 56 return; 57 } 58 } 59 mLayers.push_back(layer); 60 } 61 62 void DrawFrameTask::removeLayerUpdate(DeferredLayerUpdater* layer) { 63 for (size_t i = 0; i < mLayers.size(); i++) { 64 if (mLayers[i].get() == layer) { 65 mLayers.erase(mLayers.begin() + i); 66 return; 67 } 68 } 69 } 70 71 int DrawFrameTask::drawFrame(nsecs_t frameTimeNanos, nsecs_t recordDurationNanos) { 72 LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!"); 73 74 mSyncResult = kSync_OK; 75 mFrameTimeNanos = frameTimeNanos; 76 mRecordDurationNanos = recordDurationNanos; 77 postAndWait(); 78 79 // Reset the single-frame data 80 mFrameTimeNanos = 0; 81 mRecordDurationNanos = 0; 82 83 return mSyncResult; 84 } 85 86 void DrawFrameTask::postAndWait() { 87 AutoMutex _lock(mLock); 88 mRenderThread->queue(this); 89 mSignal.wait(mLock); 90 } 91 92 void DrawFrameTask::run() { 93 ATRACE_NAME("DrawFrame"); 94 95 mContext->profiler().setDensity(mDensity); 96 mContext->profiler().startFrame(mRecordDurationNanos); 97 98 bool canUnblockUiThread; 99 bool canDrawThisFrame; 100 { 101 TreeInfo info(TreeInfo::MODE_FULL, mRenderThread->renderState()); 102 canUnblockUiThread = syncFrameState(info); 103 canDrawThisFrame = info.out.canDrawThisFrame; 104 } 105 106 // Grab a copy of everything we need 107 CanvasContext* context = mContext; 108 109 // From this point on anything in "this" is *UNSAFE TO ACCESS* 110 if (canUnblockUiThread) { 111 unblockUiThread(); 112 } 113 114 if (CC_LIKELY(canDrawThisFrame)) { 115 context->draw(); 116 } 117 118 if (!canUnblockUiThread) { 119 unblockUiThread(); 120 } 121 } 122 123 bool DrawFrameTask::syncFrameState(TreeInfo& info) { 124 ATRACE_CALL(); 125 mRenderThread->timeLord().vsyncReceived(mFrameTimeNanos); 126 mContext->makeCurrent(); 127 Caches::getInstance().textureCache.resetMarkInUse(); 128 129 for (size_t i = 0; i < mLayers.size(); i++) { 130 mContext->processLayerUpdate(mLayers[i].get()); 131 } 132 mLayers.clear(); 133 mContext->prepareTree(info); 134 135 // This is after the prepareTree so that any pending operations 136 // (RenderNode tree state, prefetched layers, etc...) will be flushed. 137 if (CC_UNLIKELY(!mContext->hasSurface())) { 138 mSyncResult |= kSync_LostSurfaceRewardIfFound; 139 } 140 141 if (info.out.hasAnimations) { 142 if (info.out.requiresUiRedraw) { 143 mSyncResult |= kSync_UIRedrawRequired; 144 } 145 } 146 // If prepareTextures is false, we ran out of texture cache space 147 return info.prepareTextures; 148 } 149 150 void DrawFrameTask::unblockUiThread() { 151 AutoMutex _lock(mLock); 152 mSignal.signal(); 153 } 154 155 } /* namespace renderthread */ 156 } /* namespace uirenderer */ 157 } /* namespace android */ 158