DeferredDisplayList.cpp revision c3566d06421c8acc0aafb18f7e307e5725ce87e1
1c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik/*
2c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik * Copyright (C) 2013 The Android Open Source Project
3c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik *
4c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik * Licensed under the Apache License, Version 2.0 (the "License");
5c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik * you may not use this file except in compliance with the License.
6c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik * You may obtain a copy of the License at
7c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik *
8c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik *      http://www.apache.org/licenses/LICENSE-2.0
9c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik *
10c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik * Unless required by applicable law or agreed to in writing, software
11c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik * distributed under the License is distributed on an "AS IS" BASIS,
12c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik * See the License for the specific language governing permissions and
14c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik * limitations under the License.
15c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik */
16c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
17c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#define LOG_TAG "OpenGLRenderer"
18c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#define ATRACE_TAG ATRACE_TAG_VIEW
19c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
20c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#include <utils/Trace.h>
21c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
22c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#include "Debug.h"
23c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#include "DisplayListOp.h"
24c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#include "OpenGLRenderer.h"
25c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
26c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#if DEBUG_DEFER
27c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    #define DEFER_LOGD(...) ALOGD(__VA_ARGS__)
28c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#else
29c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    #define DEFER_LOGD(...)
30c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#endif
31c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
32c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craiknamespace android {
33c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craiknamespace uirenderer {
34c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
35c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craikclass DrawOpBatch {
36c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craikpublic:
37c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    DrawOpBatch() {
38c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        mOps.clear();
39c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    }
40c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
41c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    ~DrawOpBatch() {
42c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        mOps.clear();
43c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    }
44c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
45c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    void add(DrawOp* op) {
46c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        // NOTE: ignore empty bounds special case, since we don't merge across those ops
47c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        mBounds.unionWith(op->state.mBounds);
48c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        mOps.add(op);
49c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    }
50c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
51c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    bool intersects(Rect& rect) {
52c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        if (!rect.intersects(mBounds)) return false;
53c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        for (unsigned int i = 0; i < mOps.size(); i++) {
54c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            if (rect.intersects(mOps[i]->state.mBounds)) {
55c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#if DEBUG_DEFER
56c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                DEFER_LOGD("op intersects with op %p with bounds %f %f %f %f:", mOps[i],
57c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                        mOps[i]->state.mBounds.left, mOps[i]->state.mBounds.top,
58c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                        mOps[i]->state.mBounds.right, mOps[i]->state.mBounds.bottom);
59c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                mOps[i]->output(2);
60c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#endif
61c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                return true;
62c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            }
63c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        }
64c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        return false;
65c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    }
66c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
67c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    Vector<DrawOp*> mOps;
68c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craikprivate:
69c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    Rect mBounds;
70c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik};
71c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
72c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craikvoid DeferredDisplayList::clear() {
73c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    for (int i = 0; i < kOpBatch_Count; i++) {
74c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        mBatchIndices[i] = -1;
75c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    }
76c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    for (unsigned int i = 0; i < mBatches.size(); i++) {
77c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        delete mBatches[i];
78c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    }
79c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    mBatches.clear();
80c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik}
81c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
82c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craikvoid DeferredDisplayList::add(DrawOp* op, bool disallowReorder) {
83c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    if (CC_UNLIKELY(disallowReorder)) {
84c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        if (!mBatches.isEmpty()) {
85c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            mBatches[0]->add(op);
86c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            return;
87c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        }
88c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        DrawOpBatch* b = new DrawOpBatch();
89c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        b->add(op);
90c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        mBatches.add(b);
91c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        return;
92c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    }
93c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
94c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    // disallowReorder isn't set, so find the latest batch of the new op's type, and try to merge
95c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    // the new op into it
96c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    DrawOpBatch* targetBatch = NULL;
97c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    int batchId = op->getBatchId();
98c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
99c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    if (!mBatches.isEmpty()) {
100c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        if (op->state.mBounds.isEmpty()) {
101c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            // don't know the bounds for op, so add to last batch and start from scratch on next op
102c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            mBatches.top()->add(op);
103c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            for (int i = 0; i < kOpBatch_Count; i++) {
104c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                mBatchIndices[i] = -1;
105c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            }
106c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#if DEBUG_DEFER
107c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            DEFER_LOGD("Warning: Encountered op with empty bounds, resetting batches");
108c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            op->output(2);
109c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#endif
110c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            return;
111c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        }
112c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
113c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        if (batchId >= 0 && mBatchIndices[batchId] != -1) {
114c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            int targetIndex = mBatchIndices[batchId];
115c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            targetBatch = mBatches[targetIndex];
116c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            // iterate back toward target to see if anything drawn since should overlap the new op
117c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            for (int i = mBatches.size() - 1; i > targetIndex; i--) {
118c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                DrawOpBatch* overBatch = mBatches[i];
119c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                if (overBatch->intersects(op->state.mBounds)) {
120c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                    targetBatch = NULL;
121c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#if DEBUG_DEFER
122c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                    DEFER_LOGD("op couldn't join batch %d, was intersected by batch %d",
123c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                            targetIndex, i);
124c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                    op->output(2);
125c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#endif
126c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                    break;
127c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                }
128c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            }
129c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        }
130c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    }
131c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    if (!targetBatch) {
132c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        targetBatch = new DrawOpBatch();
133c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        mBatches.add(targetBatch);
134c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        if (batchId >= 0) {
135c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            mBatchIndices[batchId] = mBatches.size() - 1;
136c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        }
137c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    }
138c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    targetBatch->add(op);
139c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik}
140c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
141c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craikstatus_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty, int32_t flags,
142c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        uint32_t level) {
143c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    ATRACE_CALL();
144c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    status_t status = DrawGlInfo::kStatusDone;
145c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
146c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    if (isEmpty()) return status; // nothing to flush
147c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
148c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    DEFER_LOGD("--flushing");
149c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    DrawModifiers restoreDrawModifiers = renderer.getDrawModifiers();
150c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
151c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    int opCount = 0;
152c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    for (unsigned int i = 0; i < mBatches.size(); i++) {
153c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        DrawOpBatch* batch = mBatches[i];
154c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        for (unsigned int j = 0; j < batch->mOps.size(); j++) {
155c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            DrawOp* op = batch->mOps[j];
156c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
157c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            renderer.restoreDisplayState(op->state);
158c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
159c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#if DEBUG_DEFER
160c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            op->output(2);
161c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik#endif
162c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            status |= op->applyDraw(renderer, dirty, level,
163c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik                    op->state.mMultipliedAlpha >= 0, op->state.mMultipliedAlpha);
164c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik            opCount++;
165c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik        }
166c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    }
167c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
168c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    DEFER_LOGD("--flushed, drew %d batches (total %d ops)", mBatches.size(), opCount);
169c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    renderer.restoreToCount(restoreTo);
170c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    renderer.setDrawModifiers(restoreDrawModifiers);
171c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    clear();
172c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik    return status;
173c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik}
174c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik
175c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik}; // namespace uirenderer
176c3566d06421c8acc0aafb18f7e307e5725ce87e1Chris Craik}; // namespace android
177