DrawFrameTask.cpp revision 668f0e38ef0277d55d3118af37e17b8c435df85c
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() : mContext(0), mRenderNode(0) { 34} 35 36DrawFrameTask::~DrawFrameTask() { 37} 38 39void DrawFrameTask::setContext(CanvasContext* context) { 40 mContext = context; 41} 42 43void DrawFrameTask::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) { 44 SetDisplayListData setter; 45 setter.targetNode = renderNode; 46 setter.newData = newData; 47 mDisplayListDataUpdates.push(setter); 48} 49 50void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) { 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::setRenderNode(RenderNode* renderNode) { 64 mRenderNode = renderNode; 65} 66 67void DrawFrameTask::setDirty(int left, int top, int right, int bottom) { 68 mDirty.set(left, top, right, bottom); 69} 70 71void DrawFrameTask::drawFrame(RenderThread* renderThread) { 72 LOG_ALWAYS_FATAL_IF(!mRenderNode, "Cannot drawFrame with no render node!"); 73 LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!"); 74 75 AutoMutex _lock(mLock); 76 renderThread->queue(this); 77 mSignal.wait(mLock); 78 79 // Reset the single-frame data 80 mDirty.setEmpty(); 81 mRenderNode = 0; 82} 83 84void DrawFrameTask::run() { 85 ATRACE_NAME("DrawFrame"); 86 87 syncFrameState(); 88 89 // Grab a copy of everything we need 90 Rect dirtyCopy(mDirty); 91 RenderNode* renderNode = mRenderNode; 92 CanvasContext* context = mContext; 93 94 // This is temporary until WebView has a solution for syncing frame state 95 bool canUnblockUiThread = !requiresSynchronousDraw(renderNode); 96 97 // From this point on anything in "this" is *UNSAFE TO ACCESS* 98 if (canUnblockUiThread) { 99 unblockUiThread(); 100 } 101 102 drawRenderNode(context, renderNode, &dirtyCopy); 103 104 if (!canUnblockUiThread) { 105 unblockUiThread(); 106 } 107} 108 109void DrawFrameTask::syncFrameState() { 110 ATRACE_CALL(); 111 112 for (size_t i = 0; i < mDisplayListDataUpdates.size(); i++) { 113 const SetDisplayListData& setter = mDisplayListDataUpdates[i]; 114 setter.targetNode->setData(setter.newData); 115 } 116 mDisplayListDataUpdates.clear(); 117 118 mContext->processLayerUpdates(&mLayers); 119 mRenderNode->updateProperties(); 120} 121 122void DrawFrameTask::unblockUiThread() { 123 AutoMutex _lock(mLock); 124 mSignal.signal(); 125} 126 127void DrawFrameTask::drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty) { 128 ATRACE_CALL(); 129 130 if (dirty->bottom == -1 && dirty->left == -1 131 && dirty->top == -1 && dirty->right == -1) { 132 dirty = 0; 133 } 134 context->drawDisplayList(renderNode, dirty); 135} 136 137bool DrawFrameTask::requiresSynchronousDraw(RenderNode* renderNode) { 138 return renderNode->hasFunctors(); 139} 140 141} /* namespace renderthread */ 142} /* namespace uirenderer */ 143} /* namespace android */ 144