blob: 06a5f06e31967474a83e6033c871793f47242f94 [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
Robert Carr78c25dd2019-08-15 14:10:33 -070020#include <gui/BLASTBufferQueue.h>
21#include <gui/BufferItemConsumer.h>
22
23#include <chrono>
24
25using namespace std::chrono_literals;
26
27namespace android {
28
29BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height)
Valerie Haud3b90d22019-11-06 09:37:31 -080030 : mSurfaceControl(surface),
31 mPendingCallbacks(0),
32 mWidth(width),
33 mHeight(height),
34 mNextTransaction(nullptr) {
Robert Carr78c25dd2019-08-15 14:10:33 -070035 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
Valerie Haud3b90d22019-11-06 09:37:31 -080036 mConsumer->setMaxBufferCount(MAX_BUFFERS);
37 mProducer->setMaxDequeuedBufferCount(MAX_BUFFERS - 1);
Robert Carr78c25dd2019-08-15 14:10:33 -070038 mBufferItemConsumer =
39 new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);
40 mBufferItemConsumer->setName(String8("BLAST Consumer"));
41 mBufferItemConsumer->setFrameAvailableListener(this);
42 mBufferItemConsumer->setBufferFreedListener(this);
43 mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
44 mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888);
Valerie Hau8cee3f92019-11-06 10:06:28 -080045 mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint());
Valerie Haud3b90d22019-11-06 09:37:31 -080046
47 mAcquired = false;
Robert Carr78c25dd2019-08-15 14:10:33 -070048}
49
50void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) {
51 std::unique_lock _lock{mMutex};
52 mSurfaceControl = surface;
53 mWidth = width;
54 mHeight = height;
55 mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
Valerie Hau8cee3f92019-11-06 10:06:28 -080056 mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint());
Robert Carr78c25dd2019-08-15 14:10:33 -070057}
58
59static void transactionCallbackThunk(void* context, nsecs_t latchTime,
60 const sp<Fence>& presentFence,
61 const std::vector<SurfaceControlStats>& stats) {
62 if (context == nullptr) {
63 return;
64 }
65 BLASTBufferQueue* bq = static_cast<BLASTBufferQueue*>(context);
66 bq->transactionCallback(latchTime, presentFence, stats);
67}
68
69void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
70 const std::vector<SurfaceControlStats>& stats) {
71 std::unique_lock _lock{mMutex};
72
Valerie Haud3b90d22019-11-06 09:37:31 -080073 if (stats.size() > 0 && !mShadowQueue.empty()) {
Robert Carr78c25dd2019-08-15 14:10:33 -070074 mBufferItemConsumer->releaseBuffer(mNextCallbackBufferItem,
75 stats[0].previousReleaseFence
76 ? stats[0].previousReleaseFence
77 : Fence::NO_FENCE);
Valerie Haud3b90d22019-11-06 09:37:31 -080078 mAcquired = false;
Robert Carr78c25dd2019-08-15 14:10:33 -070079 mNextCallbackBufferItem = BufferItem();
Valerie Hau8cee3f92019-11-06 10:06:28 -080080 mBufferItemConsumer->setTransformHint(stats[0].transformHint);
Robert Carr78c25dd2019-08-15 14:10:33 -070081 }
Valerie Haud3b90d22019-11-06 09:37:31 -080082 mPendingCallbacks--;
83 processNextBufferLocked();
84 mCallbackCV.notify_all();
Robert Carr78c25dd2019-08-15 14:10:33 -070085 decStrong((void*)transactionCallbackThunk);
86}
87
Valerie Haud3b90d22019-11-06 09:37:31 -080088void BLASTBufferQueue::processNextBufferLocked() {
89 if (mShadowQueue.empty()) {
90 return;
91 }
92
93 if (mAcquired) {
94 return;
95 }
96
97 BufferItem item = std::move(mShadowQueue.front());
98 mShadowQueue.pop();
Robert Carr78c25dd2019-08-15 14:10:33 -070099
100 SurfaceComposerClient::Transaction localTransaction;
101 bool applyTransaction = true;
102 SurfaceComposerClient::Transaction* t = &localTransaction;
103 if (mNextTransaction != nullptr) {
104 t = mNextTransaction;
105 mNextTransaction = nullptr;
106 applyTransaction = false;
107 }
108
Robert Carr78c25dd2019-08-15 14:10:33 -0700109 mNextCallbackBufferItem = mLastSubmittedBufferItem;
Robert Carr78c25dd2019-08-15 14:10:33 -0700110 mLastSubmittedBufferItem = BufferItem();
Valerie Haud3b90d22019-11-06 09:37:31 -0800111
112 status_t status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false);
113 mAcquired = true;
Robert Carr78c25dd2019-08-15 14:10:33 -0700114 if (status != OK) {
115 ALOGE("Failed to acquire?");
116 }
117
118 auto buffer = mLastSubmittedBufferItem.mGraphicBuffer;
119
120 if (buffer == nullptr) {
121 ALOGE("Null buffer");
122 return;
123 }
124
Robert Carr78c25dd2019-08-15 14:10:33 -0700125 // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
126 incStrong((void*)transactionCallbackThunk);
127
128 t->setBuffer(mSurfaceControl, buffer);
129 t->setAcquireFence(mSurfaceControl,
130 item.mFence ? new Fence(item.mFence->dup()) : Fence::NO_FENCE);
131 t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
132
133 t->setFrame(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
134 t->setCrop(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
135
136 if (applyTransaction) {
Robert Carr78c25dd2019-08-15 14:10:33 -0700137 t->apply();
Robert Carr78c25dd2019-08-15 14:10:33 -0700138 }
139}
140
Valerie Haud3b90d22019-11-06 09:37:31 -0800141void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
142 std::lock_guard _lock{mMutex};
143
144 // add to shadow queue
145 mShadowQueue.push(item);
146 processNextBufferLocked();
147 mPendingCallbacks++;
148}
149
Robert Carr78c25dd2019-08-15 14:10:33 -0700150void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) {
Valerie Haud3b90d22019-11-06 09:37:31 -0800151 std::lock_guard _lock{mMutex};
Robert Carr78c25dd2019-08-15 14:10:33 -0700152 mNextTransaction = t;
153}
154
155} // namespace android