blob: 3a369cdd431e6f91dc6d026905836d6d3ece24e2 [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);
36}
37
38void BLASTBufferQueue::update(const sp<SurfaceControl>& surface, int width, int height) {
39 std::unique_lock _lock{mMutex};
40 mSurfaceControl = surface;
41 mWidth = width;
42 mHeight = height;
43 mBufferItemConsumer->setDefaultBufferSize(mWidth, mHeight);
44}
45
46static void transactionCallbackThunk(void* context, nsecs_t latchTime,
47 const sp<Fence>& presentFence,
48 const std::vector<SurfaceControlStats>& stats) {
49 if (context == nullptr) {
50 return;
51 }
52 BLASTBufferQueue* bq = static_cast<BLASTBufferQueue*>(context);
53 bq->transactionCallback(latchTime, presentFence, stats);
54}
55
56void BLASTBufferQueue::transactionCallback(nsecs_t /*latchTime*/, const sp<Fence>& /*presentFence*/,
57 const std::vector<SurfaceControlStats>& stats) {
58 std::unique_lock _lock{mMutex};
59
60 if (stats.size() > 0 && mNextCallbackBufferItem.mGraphicBuffer != nullptr) {
61 mBufferItemConsumer->releaseBuffer(mNextCallbackBufferItem,
62 stats[0].previousReleaseFence
63 ? stats[0].previousReleaseFence
64 : Fence::NO_FENCE);
65 mNextCallbackBufferItem = BufferItem();
66 }
67 mDequeueWaitCV.notify_one();
68 decStrong((void*)transactionCallbackThunk);
69}
70
71void BLASTBufferQueue::onFrameAvailable(const BufferItem& item) {
72 std::unique_lock _lock{mMutex};
73
74 SurfaceComposerClient::Transaction localTransaction;
75 bool applyTransaction = true;
76 SurfaceComposerClient::Transaction* t = &localTransaction;
77 if (mNextTransaction != nullptr) {
78 t = mNextTransaction;
79 mNextTransaction = nullptr;
80 applyTransaction = false;
81 }
82
83 int status = OK;
84 mNextCallbackBufferItem = mLastSubmittedBufferItem;
85
86 mLastSubmittedBufferItem = BufferItem();
87 status = mBufferItemConsumer->acquireBuffer(&mLastSubmittedBufferItem, -1, false);
88 if (status != OK) {
89 ALOGE("Failed to acquire?");
90 }
91
92 auto buffer = mLastSubmittedBufferItem.mGraphicBuffer;
93
94 if (buffer == nullptr) {
95 ALOGE("Null buffer");
96 return;
97 }
98
99
100 // Ensure BLASTBufferQueue stays alive until we receive the transaction complete callback.
101 incStrong((void*)transactionCallbackThunk);
102
103 t->setBuffer(mSurfaceControl, buffer);
104 t->setAcquireFence(mSurfaceControl,
105 item.mFence ? new Fence(item.mFence->dup()) : Fence::NO_FENCE);
106 t->addTransactionCompletedCallback(transactionCallbackThunk, static_cast<void*>(this));
107
108 t->setFrame(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
109 t->setCrop(mSurfaceControl, {0, 0, (int32_t)buffer->getWidth(), (int32_t)buffer->getHeight()});
110
111 if (applyTransaction) {
112 ALOGE("Apply transaction");
113 t->apply();
114
115 if (mNextCallbackBufferItem.mGraphicBuffer != nullptr) {
116 mDequeueWaitCV.wait_for(_lock, 5000ms);
117 }
118 }
119}
120
121void BLASTBufferQueue::setNextTransaction(SurfaceComposerClient::Transaction* t) {
122 std::unique_lock _lock{mMutex};
123 mNextTransaction = t;
124}
125
126} // namespace android