blob: a5e5693ff4f66e70fb8c3c8a848d740297681b6b [file] [log] [blame]
Robert Carr78c25dd2019-08-15 14:10:33 -07001/*
2 * Copyright (C) 2019 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
Valerie Haud3b90d22019-11-06 09:37:31 -080017#undef LOG_TAG
18#define LOG_TAG "BLASTBufferQueue"
19
Valerie Haua32c5522019-12-09 10:11:08 -080020#define ATRACE_TAG ATRACE_TAG_GRAPHICS
21
Robert Carr78c25dd2019-08-15 14:10:33 -070022#include <gui/BLASTBufferQueue.h>
23#include <gui/BufferItemConsumer.h>
Valerie Hau45e4b3b2019-12-03 10:49:17 -080024#include <gui/GLConsumer.h>
Robert Carr78c25dd2019-08-15 14:10:33 -070025
Valerie Haua32c5522019-12-09 10:11:08 -080026#include <utils/Trace.h>
27
Robert Carr78c25dd2019-08-15 14:10:33 -070028#include <chrono>
29
30using namespace std::chrono_literals;
31
32namespace android {
33
34BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height)
Valerie Haud3b90d22019-11-06 09:37:31 -080035 : mSurfaceControl(surface),
Valerie Haud3b90d22019-11-06 09:37:31 -080036 mWidth(width),
37 mHeight(height),
38 mNextTransaction(nullptr) {
Robert Carr78c25dd2019-08-15 14:10:33 -070039 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
Valerie Haud3b90d22019-11-06 09:37:31 -080040 mConsumer->setMaxBufferCount(MAX_BUFFERS);
41 mProducer->setMaxDequeuedBufferCount(MAX_BUFFERS - 1);
Valerie Haua32c5522019-12-09 10:11:08 -080042 mConsumer->setMaxAcquiredBufferCount(MAX_ACQUIRED_BUFFERS);
Robert Carr78c25dd2019-08-15 14:10:33 -070043 mBufferItemConsumer =
44 new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);
Valerie Haua32c5522019-12-09 10:11:08 -080045 static int32_t id = 0;
46 auto name = std::string("BLAST Consumer") + std::to_string(id);
47 id++;
48 mBufferItemConsumer->setName(String8(name.c_str()));
Robert Carr78c25dd2019-08-15 14:10:33 -070049 mBufferItemConsumer->setFrameAvailableListener(this);
50 mBufferItemConsumer->setBufferFreedListener(this);
51 mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
52 mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888);
Valerie Hau8cee3f92019-11-06 10:06:28 -080053 mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint());
Valerie Haud3b90d22019-11-06 09:37:31 -080054
Valerie Haua32c5522019-12-09 10:11:08 -080055 mNumAcquired = 0;
56 mNumFrameAvailable = 0;
57 mPendingReleaseItem.item = BufferItem();
58 mPendingReleaseItem.releaseFence = nullptr;
Robert Carr78c25dd2019-08-15 14:10:33 -070059}
60
61void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) {
62 std::unique_lock _lock{mMutex};
63 mSurfaceControl = surface;
64 mWidth = width;
65 mHeight = height;
66 mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
Valerie Hau8cee3f92019-11-06 10:06:28 -080067 mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint());
Robert Carr78c25dd2019-08-15 14:10:33 -070068}
69
70static void transactionCallbackThunk(void* context, nsecs_t latchTime,
71 const sp<Fence>& presentFence,
72 const std::vector<SurfaceControlStats>& stats) {
73 if (context == nullptr) {
74 return;
75 }
76 BLASTBufferQueue* bq = static_cast<BLASTBufferQueue*>(context);
77 bq->transactionCallback(latchTime, presentFence, stats);
78}
79
80void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
81 const std::vector<SurfaceControlStats>& stats) {
82 std::unique_lock _lock{mMutex};
Valerie Haua32c5522019-12-09 10:11:08 -080083 ATRACE_CALL();
Robert Carr78c25dd2019-08-15 14:10:33 -070084
Valerie Haua32c5522019-12-09 10:11:08 -080085 if (mPendingReleaseItem.item.mGraphicBuffer != nullptr) {
86 if (stats.size() > 0) {
87 mPendingReleaseItem.releaseFence = stats[0].previousReleaseFence;
88 mTransformHint = stats[0].transformHint;
89 } else {
90 ALOGE("Warning: no SurfaceControlStats returned in BLASTBufferQueue callback");
91 mPendingReleaseItem.releaseFence = nullptr;
92 }
93 mBufferItemConsumer->releaseBuffer(mPendingReleaseItem.item,
94 mPendingReleaseItem.releaseFence
95 ? mPendingReleaseItem.releaseFence
Robert Carr78c25dd2019-08-15 14:10:33 -070096 : Fence::NO_FENCE);
Valerie Haua32c5522019-12-09 10:11:08 -080097 mNumAcquired--;
98 mPendingReleaseItem.item = BufferItem();
99 mPendingReleaseItem.releaseFence = nullptr;
Robert Carr78c25dd2019-08-15 14:10:33 -0700100 }
Valerie Haua32c5522019-12-09 10:11:08 -0800101
102 if (mSubmitted.empty()) {
103 ALOGE("ERROR: callback with no corresponding submitted buffer item");
104 }
105 mPendingReleaseItem.item = std::move(mSubmitted.front());
106 mSubmitted.pop();
Valerie Haud3b90d22019-11-06 09:37:31 -0800107 processNextBufferLocked();
108 mCallbackCV.notify_all();
Robert Carr78c25dd2019-08-15 14:10:33 -0700109 decStrong((void*)transactionCallbackThunk);
110}
111
Valerie Haud3b90d22019-11-06 09:37:31 -0800112void BLASTBufferQueue::processNextBufferLocked() {
Valerie Haua32c5522019-12-09 10:11:08 -0800113 ATRACE_CALL();
114 if (mNumFrameAvailable == 0) {
Valerie Haud3b90d22019-11-06 09:37:31 -0800115 return;
116 }
117
Valerie Haua32c5522019-12-09 10:11:08 -0800118 if (mSurfaceControl == nullptr) {
119 ALOGE("ERROR : surface control is null");
Valerie Haud3b90d22019-11-06 09:37:31 -0800120 return;
121 }
122
Robert Carr78c25dd2019-08-15 14:10:33 -0700123 SurfaceComposerClient::Transaction localTransaction;
124 bool applyTransaction = true;
125 SurfaceComposerClient::Transaction* t = &localTransaction;
126 if (mNextTransaction != nullptr) {
127 t = mNextTransaction;
128 mNextTransaction = nullptr;
129 applyTransaction = false;
130 }
131
Valerie Haua32c5522019-12-09 10:11:08 -0800132 BufferItem bufferItem;
Valerie Haud3b90d22019-11-06 09:37:31 -0800133
Valerie Haua32c5522019-12-09 10:11:08 -0800134 status_t status = mBufferItemConsumer->acquireBuffer(&bufferItem, -1, false);
Robert Carr78c25dd2019-08-15 14:10:33 -0700135 if (status != OK) {
Robert Carr78c25dd2019-08-15 14:10:33 -0700136 return;
137 }
Valerie Haua32c5522019-12-09 10:11:08 -0800138 auto buffer = bufferItem.mGraphicBuffer;
139 mNumFrameAvailable--;
140
141 if (buffer == nullptr) {
142 mBufferItemConsumer->releaseBuffer(bufferItem, Fence::NO_FENCE);
143 return;
144 }
145
146 mNumAcquired++;
147 mSubmitted.push(bufferItem);
Robert Carr78c25dd2019-08-15 14:10:33 -0700148
Robert Carr78c25dd2019-08-15 14:10:33 -0700149 // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
150 incStrong((void*)transactionCallbackThunk);
151
152 t->setBuffer(mSurfaceControl, buffer);
153 t->setAcquireFence(mSurfaceControl,
Valerie Haua32c5522019-12-09 10:11:08 -0800154 bufferItem.mFence ? new Fence(bufferItem.mFence->dup()) : Fence::NO_FENCE);
Robert Carr78c25dd2019-08-15 14:10:33 -0700155 t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
156
157 t->setFrame(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
Valerie Haua32c5522019-12-09 10:11:08 -0800158 t->setCrop(mSurfaceControl, computeCrop(bufferItem));
159 t->setTransform(mSurfaceControl, bufferItem.mTransform);
Robert Carr78c25dd2019-08-15 14:10:33 -0700160
161 if (applyTransaction) {
Robert Carr78c25dd2019-08-15 14:10:33 -0700162 t->apply();
Robert Carr78c25dd2019-08-15 14:10:33 -0700163 }
164}
165
Valerie Hau45e4b3b2019-12-03 10:49:17 -0800166Rect BLASTBufferQueue::computeCrop(const BufferItem& item) {
167 if (item.mScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
168 return GLConsumer::scaleDownCrop(item.mCrop, mWidth, mHeight);
169 }
170 return item.mCrop;
171}
172
Valerie Haua32c5522019-12-09 10:11:08 -0800173void BLASTBufferQueue::onFrameAvailable(const BufferItem& /*item*/) {
174 ATRACE_CALL();
Valerie Haud3b90d22019-11-06 09:37:31 -0800175 std::lock_guard _lock{mMutex};
176
177 // add to shadow queue
Valerie Haua32c5522019-12-09 10:11:08 -0800178 mNumFrameAvailable++;
Valerie Haud3b90d22019-11-06 09:37:31 -0800179 processNextBufferLocked();
Valerie Haud3b90d22019-11-06 09:37:31 -0800180}
181
Robert Carr78c25dd2019-08-15 14:10:33 -0700182void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) {
Valerie Haud3b90d22019-11-06 09:37:31 -0800183 std::lock_guard _lock{mMutex};
Robert Carr78c25dd2019-08-15 14:10:33 -0700184 mNextTransaction = t;
185}
186
187} // namespace android