1668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck/*
2668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck * Copyright (C) 2014 The Android Open Source Project
3668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck *
4668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck * Licensed under the Apache License, Version 2.0 (the "License");
5668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck * you may not use this file except in compliance with the License.
6668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck * You may obtain a copy of the License at
7668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck *
8668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck *      http://www.apache.org/licenses/LICENSE-2.0
9668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck *
10668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck * Unless required by applicable law or agreed to in writing, software
11668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck * distributed under the License is distributed on an "AS IS" BASIS,
12668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck * See the License for the specific language governing permissions and
14668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck * limitations under the License.
15668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck */
16668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
17668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck#include "DrawFrameTask.h"
18668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
19668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck#include <utils/Log.h>
20668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck#include <utils/Trace.h>
21668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
22d72e0a339b54af0c4e731513bbad120dff694723John Reck#include "../DeferredLayerUpdater.h"
23668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck#include "../DisplayList.h"
24668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck#include "../RenderNode.h"
25668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck#include "CanvasContext.h"
26668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck#include "RenderThread.h"
27668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
28668f0e38ef0277d55d3118af37e17b8c435df85cJohn Recknamespace android {
29668f0e38ef0277d55d3118af37e17b8c435df85cJohn Recknamespace uirenderer {
30668f0e38ef0277d55d3118af37e17b8c435df85cJohn Recknamespace renderthread {
31668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
3218f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn ReckDrawFrameTask::DrawFrameTask()
33d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        : mRenderThread(nullptr)
34d41c4d8c732095ae99c955b6b82f7306633004b1Chris Craik        , mContext(nullptr)
359a17da8125c36c82ba73e7f4b3ed80b9c633767fJohn Reck        , mSyncResult(SyncResult::OK) {
36668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck}
37668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
38668f0e38ef0277d55d3118af37e17b8c435df85cJohn ReckDrawFrameTask::~DrawFrameTask() {
39668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck}
40668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
41ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhnevoid DrawFrameTask::setContext(RenderThread* thread, CanvasContext* context,
42ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne        RenderNode* targetNode) {
4318f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck    mRenderThread = thread;
44668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    mContext = context;
45ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    mTargetNode = targetNode;
46668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck}
47668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
48d72e0a339b54af0c4e731513bbad120dff694723John Reckvoid DrawFrameTask::pushLayerUpdate(DeferredLayerUpdater* layer) {
49d72e0a339b54af0c4e731513bbad120dff694723John Reck    LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to pushLayerUpdate with!");
50087bc0c14bdccf7c258dce0cdef46a69a839b427John Reck
51d72e0a339b54af0c4e731513bbad120dff694723John Reck    for (size_t i = 0; i < mLayers.size(); i++) {
52d72e0a339b54af0c4e731513bbad120dff694723John Reck        if (mLayers[i].get() == layer) {
53d72e0a339b54af0c4e731513bbad120dff694723John Reck            return;
54d72e0a339b54af0c4e731513bbad120dff694723John Reck        }
55d72e0a339b54af0c4e731513bbad120dff694723John Reck    }
56d72e0a339b54af0c4e731513bbad120dff694723John Reck    mLayers.push_back(layer);
57668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck}
58668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
59d72e0a339b54af0c4e731513bbad120dff694723John Reckvoid DrawFrameTask::removeLayerUpdate(DeferredLayerUpdater* layer) {
60668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    for (size_t i = 0; i < mLayers.size(); i++) {
61d72e0a339b54af0c4e731513bbad120dff694723John Reck        if (mLayers[i].get() == layer) {
62d72e0a339b54af0c4e731513bbad120dff694723John Reck            mLayers.erase(mLayers.begin() + i);
63d72e0a339b54af0c4e731513bbad120dff694723John Reck            return;
64668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck        }
65668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    }
66668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck}
67668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
682de950d5a8b47c7b4648ada1b1260ce4b7342798John Reckint DrawFrameTask::drawFrame() {
69668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
70668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
719a17da8125c36c82ba73e7f4b3ed80b9c633767fJohn Reck    mSyncResult = SyncResult::OK;
72be3fba05e823f740f65b2679929347dc3dd282adJohn Reck    mSyncQueued = systemTime(CLOCK_MONOTONIC);
7318f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reck    postAndWait();
74668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
75f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    return mSyncResult;
76668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck}
77668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
7818f16e6fba74eda173e1e7c869e6e2e2acc073ffJohn Reckvoid DrawFrameTask::postAndWait() {
79087bc0c14bdccf7c258dce0cdef46a69a839b427John Reck    AutoMutex _lock(mLock);
80738ec3aace180018560998d1c2cdeb9ddde5fbfaChris Craik    mRenderThread->queue(this);
81738ec3aace180018560998d1c2cdeb9ddde5fbfaChris Craik    mSignal.wait(mLock);
82087bc0c14bdccf7c258dce0cdef46a69a839b427John Reck}
83087bc0c14bdccf7c258dce0cdef46a69a839b427John Reck
84668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reckvoid DrawFrameTask::run() {
85668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    ATRACE_NAME("DrawFrame");
86668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
87a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    bool canUnblockUiThread;
88a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    bool canDrawThisFrame;
89a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    {
90e2e53a7079733694bd52dbce665e9ceff21e9727Chris Craik        TreeInfo info(TreeInfo::MODE_FULL, *mContext);
91a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck        canUnblockUiThread = syncFrameState(info);
92a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck        canDrawThisFrame = info.out.canDrawThisFrame;
93a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    }
94668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
95668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    // Grab a copy of everything we need
96668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    CanvasContext* context = mContext;
97668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
98668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    // From this point on anything in "this" is *UNSAFE TO ACCESS*
99668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    if (canUnblockUiThread) {
100668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck        unblockUiThread();
101668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    }
102668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
103a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    if (CC_LIKELY(canDrawThisFrame)) {
104e4267ea4f20740c37c01bfb6aefcf61fddc4566aJohn Reck        context->draw();
10506e2e9cf4c3fe1eaac3271c9a346d5cc7fe5c3a8Chris Craik    } else {
10606e2e9cf4c3fe1eaac3271c9a346d5cc7fe5c3a8Chris Craik        // wait on fences so tasks don't overlap next frame
10706e2e9cf4c3fe1eaac3271c9a346d5cc7fe5c3a8Chris Craik        context->waitOnFences();
108a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reck    }
109668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
110668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    if (!canUnblockUiThread) {
111668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck        unblockUiThread();
112668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    }
113668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck}
114668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
115a5dda645da738da7b4ae15e28fa7d93d3b04b94fJohn Reckbool DrawFrameTask::syncFrameState(TreeInfo& info) {
116668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    ATRACE_CALL();
1171b54fb27ac48495ed0b33868fda5776fb49fe0f3Chris Craik    int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::Vsync)];
118c87be99c6ead0720a8918ea38ce3b25e5c49e1c6John Reck    mRenderThread->timeLord().vsyncReceived(vsync);
1198afcc76920499d0a384dba1470c5a377f80ed768John Reck    bool canDraw = mContext->makeCurrent();
120b7d34b64dd32e3d84bd43344c9c3d9ad098129afDerek Sollenberger    mContext->unpinImages();
121d72e0a339b54af0c4e731513bbad120dff694723John Reck
122d72e0a339b54af0c4e731513bbad120dff694723John Reck    for (size_t i = 0; i < mLayers.size(); i++) {
123d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        mLayers[i]->apply();
124d72e0a339b54af0c4e731513bbad120dff694723John Reck    }
125d72e0a339b54af0c4e731513bbad120dff694723John Reck    mLayers.clear();
126ea7a7fb75acb7305eb774ca7bc7e96103bd49323Skuhne    mContext->prepareTree(info, mFrameInfo, mSyncQueued, mTargetNode);
127d72e0a339b54af0c4e731513bbad120dff694723John Reck
128aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck    // This is after the prepareTree so that any pending operations
129aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck    // (RenderNode tree state, prefetched layers, etc...) will be flushed.
1308afcc76920499d0a384dba1470c5a377f80ed768John Reck    if (CC_UNLIKELY(!mContext->hasSurface() || !canDraw)) {
1319a17da8125c36c82ba73e7f4b3ed80b9c633767fJohn Reck        if (!mContext->hasSurface()) {
1329a17da8125c36c82ba73e7f4b3ed80b9c633767fJohn Reck            mSyncResult |= SyncResult::LostSurfaceRewardIfFound;
1339a17da8125c36c82ba73e7f4b3ed80b9c633767fJohn Reck        } else {
1349a17da8125c36c82ba73e7f4b3ed80b9c633767fJohn Reck            // If we have a surface but can't draw we must be stopped
1359a17da8125c36c82ba73e7f4b3ed80b9c633767fJohn Reck            mSyncResult |= SyncResult::ContextIsStopped;
1369a17da8125c36c82ba73e7f4b3ed80b9c633767fJohn Reck        }
1378afcc76920499d0a384dba1470c5a377f80ed768John Reck        info.out.canDrawThisFrame = false;
138aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck    }
139aa95a88327d9a3ac8a4a00b065b78ac0f28b3a19John Reck
140f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck    if (info.out.hasAnimations) {
141f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck        if (info.out.requiresUiRedraw) {
1429a17da8125c36c82ba73e7f4b3ed80b9c633767fJohn Reck            mSyncResult |= SyncResult::UIRedrawRequired;
143f9be77940e365036fecd8cc0e491e8545c34e79bJohn Reck        }
14452244fff29042926e21fa897ef5ab11148e35299John Reck    }
145860d155f866cc15a725e7ce03763280987f24901John Reck    // If prepareTextures is false, we ran out of texture cache space
146826b56448691221e4cfe2f19a09c3d8790f78d2cBo Liu    return info.prepareTextures;
147668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck}
148668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
149668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reckvoid DrawFrameTask::unblockUiThread() {
150668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    AutoMutex _lock(mLock);
151668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck    mSignal.signal();
152668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck}
153668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck
154668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck} /* namespace renderthread */
155668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck} /* namespace uirenderer */
156668f0e38ef0277d55d3118af37e17b8c435df85cJohn Reck} /* namespace android */
157