blob: 29ea84e76d544d341ad854b696f2c90f048857aa [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>
Valerie Hau45e4b3b2019-12-03 10:49:17 -080022#include <gui/GLConsumer.h>
Robert Carr78c25dd2019-08-15 14:10:33 -070023
24#include <chrono>
25
26using namespace std::chrono_literals;
27
28namespace android {
29
30BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height)
Valerie Haud3b90d22019-11-06 09:37:31 -080031 : mSurfaceControl(surface),
32 mPendingCallbacks(0),
33 mWidth(width),
34 mHeight(height),
35 mNextTransaction(nullptr) {
Robert Carr78c25dd2019-08-15 14:10:33 -070036 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
Valerie Haud3b90d22019-11-06 09:37:31 -080037 mConsumer->setMaxBufferCount(MAX_BUFFERS);
38 mProducer->setMaxDequeuedBufferCount(MAX_BUFFERS - 1);
Robert Carr78c25dd2019-08-15 14:10:33 -070039 mBufferItemConsumer =
40 new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);
41 mBufferItemConsumer->setName(String8("BLAST Consumer"));
42 mBufferItemConsumer->setFrameAvailableListener(this);
43 mBufferItemConsumer->setBufferFreedListener(this);
44 mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
45 mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888);
Valerie Hau8cee3f92019-11-06 10:06:28 -080046 mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint());
Valerie Haud3b90d22019-11-06 09:37:31 -080047
48 mAcquired = false;
Robert Carr78c25dd2019-08-15 14:10:33 -070049}
50
51void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) {
52 std::unique_lock _lock{mMutex};
53 mSurfaceControl = surface;
54 mWidth = width;
55 mHeight = height;
56 mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
Valerie Hau8cee3f92019-11-06 10:06:28 -080057 mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint());
Robert Carr78c25dd2019-08-15 14:10:33 -070058}
59
60static void transactionCallbackThunk(void* context, nsecs_t latchTime,
61 const sp<Fence>& presentFence,
62 const std::vector<SurfaceControlStats>& stats) {
63 if (context == nullptr) {
64 return;
65 }
66 BLASTBufferQueue* bq = static_cast<BLASTBufferQueue*>(context);
67 bq->transactionCallback(latchTime, presentFence, stats);
68}
69
70void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
71 const std::vector<SurfaceControlStats>& stats) {
72 std::unique_lock _lock{mMutex};
73
Valerie Haud3b90d22019-11-06 09:37:31 -080074 if (stats.size() > 0 && !mShadowQueue.empty()) {
Robert Carr78c25dd2019-08-15 14:10:33 -070075 mBufferItemConsumer->releaseBuffer(mNextCallbackBufferItem,
76 stats[0].previousReleaseFence
77 ? stats[0].previousReleaseFence
78 : Fence::NO_FENCE);
Valerie Haud3b90d22019-11-06 09:37:31 -080079 mAcquired = false;
Robert Carr78c25dd2019-08-15 14:10:33 -070080 mNextCallbackBufferItem = BufferItem();
Valerie Hau8cee3f92019-11-06 10:06:28 -080081 mBufferItemConsumer->setTransformHint(stats[0].transformHint);
Robert Carr78c25dd2019-08-15 14:10:33 -070082 }
Valerie Haud3b90d22019-11-06 09:37:31 -080083 mPendingCallbacks--;
84 processNextBufferLocked();
85 mCallbackCV.notify_all();
Robert Carr78c25dd2019-08-15 14:10:33 -070086 decStrong((void*)transactionCallbackThunk);
87}
88
Valerie Haud3b90d22019-11-06 09:37:31 -080089void BLASTBufferQueue::processNextBufferLocked() {
90 if (mShadowQueue.empty()) {
91 return;
92 }
93
94 if (mAcquired) {
95 return;
96 }
97
98 BufferItem item = std::move(mShadowQueue.front());
99 mShadowQueue.pop();
Robert Carr78c25dd2019-08-15 14:10:33 -0700100
101 SurfaceComposerClient::Transaction localTransaction;
102 bool applyTransaction = true;
103 SurfaceComposerClient::Transaction* t = &localTransaction;
104 if (mNextTransaction != nullptr) {
105 t = mNextTransaction;
106 mNextTransaction = nullptr;
107 applyTransaction = false;
108 }
109
Robert Carr78c25dd2019-08-15 14:10:33 -0700110 mNextCallbackBufferItem = mLastSubmittedBufferItem;
Robert Carr78c25dd2019-08-15 14:10:33 -0700111 mLastSubmittedBufferItem = BufferItem();
Valerie Haud3b90d22019-11-06 09:37:31 -0800112
113 status_t status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false);
114 mAcquired = true;
Robert Carr78c25dd2019-08-15 14:10:33 -0700115 if (status != OK) {
116 ALOGE("Failed to acquire?");
117 }
118
119 auto buffer = mLastSubmittedBufferItem.mGraphicBuffer;
120
121 if (buffer == nullptr) {
122 ALOGE("Null buffer");
123 return;
124 }
125
Robert Carr78c25dd2019-08-15 14:10:33 -0700126 // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
127 incStrong((void*)transactionCallbackThunk);
128
129 t->setBuffer(mSurfaceControl, buffer);
130 t->setAcquireFence(mSurfaceControl,
131 item.mFence ? new Fence(item.mFence->dup()) : Fence::NO_FENCE);
132 t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
133
134 t->setFrame(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
Valerie Hau45e4b3b2019-12-03 10:49:17 -0800135 t->setCrop(mSurfaceControl, computeCrop(mLastSubmittedBufferItem));
Robert Carr78c25dd2019-08-15 14:10:33 -0700136
137 if (applyTransaction) {
Robert Carr78c25dd2019-08-15 14:10:33 -0700138 t->apply();
Robert Carr78c25dd2019-08-15 14:10:33 -0700139 }
140}
141
Valerie Hau45e4b3b2019-12-03 10:49:17 -0800142Rect BLASTBufferQueue::computeCrop(const BufferItem& item) {
143 if (item.mScalingMode == NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
144 return GLConsumer::scaleDownCrop(item.mCrop, mWidth, mHeight);
145 }
146 return item.mCrop;
147}
148
Valerie Haud3b90d22019-11-06 09:37:31 -0800149void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
150 std::lock_guard _lock{mMutex};
151
152 // add to shadow queue
153 mShadowQueue.push(item);
154 processNextBufferLocked();
155 mPendingCallbacks++;
156}
157
Robert Carr78c25dd2019-08-15 14:10:33 -0700158void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) {
Valerie Haud3b90d22019-11-06 09:37:31 -0800159 std::lock_guard _lock{mMutex};
Robert Carr78c25dd2019-08-15 14:10:33 -0700160 mNextTransaction = t;
161}
162
163} // namespace android