blob: 3c31d7439f2bde73d2e6dd20dc3d30513d7e34c8 [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
17#include <gui/BLASTBufferQueue.h>
18#include <gui/BufferItemConsumer.h>
19
20#include <chrono>
21
22using namespace std::chrono_literals;
23
24namespace android {
25
26BLASTBufferQueue::BLASTBufferQueue(const sp<SurfaceControl>& surface, int width, int height)
27 : mSurfaceControl(surface), mWidth(width), mHeight(height) {
28 BufferQueue::createBufferQueue(&mProducer, &mConsumer);
29 mBufferItemConsumer =
30 new BufferItemConsumer(mConsumer, AHARDWAREBUFFER_USAGE_GPU_FRAMEBUFFER, 1, true);
31 mBufferItemConsumer->setName(String8("BLAST Consumer"));
32 mBufferItemConsumer->setFrameAvailableListener(this);
33 mBufferItemConsumer->setBufferFreedListener(this);
34 mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
35 mBufferItemConsumer->setDefaultBufferFormat(PIXEL_FORMAT_RGBA_8888);
Valerie Hau8cee3f92019-11-06 10:06:28 -080036 mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint());
Robert Carr78c25dd2019-08-15 14:10:33 -070037}
38
39void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) {
40 std::unique_lock _lock{mMutex};
41 mSurfaceControl = surface;
42 mWidth = width;
43 mHeight = height;
44 mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
Valerie Hau8cee3f92019-11-06 10:06:28 -080045 mBufferItemConsumer->setTransformHint(mSurfaceControl->getTransformHint());
Robert Carr78c25dd2019-08-15 14:10:33 -070046}
47
48static void transactionCallbackThunk(void* context, nsecs_t latchTime,
49 const sp<Fence>& presentFence,
50 const std::vector<SurfaceControlStats>& stats) {
51 if (context == nullptr) {
52 return;
53 }
54 BLASTBufferQueue* bq = static_cast<BLASTBufferQueue*>(context);
55 bq->transactionCallback(latchTime, presentFence, stats);
56}
57
58void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
59 const std::vector<SurfaceControlStats>& stats) {
60 std::unique_lock _lock{mMutex};
61
62 if (stats.size() > 0 && mNextCallbackBufferItem.mGraphicBuffer != nullptr) {
63 mBufferItemConsumer->releaseBuffer(mNextCallbackBufferItem,
64 stats[0].previousReleaseFence
65 ? stats[0].previousReleaseFence
66 : Fence::NO_FENCE);
67 mNextCallbackBufferItem = BufferItem();
Valerie Hau8cee3f92019-11-06 10:06:28 -080068 mBufferItemConsumer->setTransformHint(stats[0].transformHint);
Robert Carr78c25dd2019-08-15 14:10:33 -070069 }
Valerie Hauda3446e2019-10-14 15:49:22 -070070 mDequeueWaitCV.notify_all();
Robert Carr78c25dd2019-08-15 14:10:33 -070071 decStrong((void*)transactionCallbackThunk);
72}
73
74void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
75 std::unique_lock _lock{mMutex};
76
77 SurfaceComposerClient::Transaction localTransaction;
78 bool applyTransaction = true;
79 SurfaceComposerClient::Transaction* t = &localTransaction;
80 if (mNextTransaction != nullptr) {
81 t = mNextTransaction;
82 mNextTransaction = nullptr;
83 applyTransaction = false;
84 }
85
86 int status = OK;
87 mNextCallbackBufferItem = mLastSubmittedBufferItem;
88
89 mLastSubmittedBufferItem = BufferItem();
90 status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false);
91 if (status != OK) {
92 ALOGE("Failed to acquire?");
93 }
94
95 auto buffer = mLastSubmittedBufferItem.mGraphicBuffer;
96
97 if (buffer == nullptr) {
98 ALOGE("Null buffer");
99 return;
100 }
101
102
103 // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
104 incStrong((void*)transactionCallbackThunk);
105
106 t->setBuffer(mSurfaceControl, buffer);
107 t->setAcquireFence(mSurfaceControl,
108 item.mFence ? new Fence(item.mFence->dup()) : Fence::NO_FENCE);
109 t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
110
111 t->setFrame(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
112 t->setCrop(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
113
114 if (applyTransaction) {
115 ALOGE("Apply transaction");
116 t->apply();
117
118 if (mNextCallbackBufferItem.mGraphicBuffer != nullptr) {
119 mDequeueWaitCV.wait_for(_lock, 5000ms);
120 }
121 }
122}
123
124void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) {
125 std::unique_lock _lock{mMutex};
126 mNextTransaction = t;
127}
128
129} // namespace android