xref: /aosp_15_r20/frameworks/av/services/camera/virtualcamera/util/EglSurfaceTexture.cc (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1 /*
2  * Copyright (C) 2023 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 // #define LOG_NDEBUG 0
18 #include <chrono>
19 
20 #include "utils/Timers.h"
21 #define LOG_TAG "EglSurfaceTexture"
22 
23 #include <GLES/gl.h>
24 #include <com_android_graphics_libgui_flags.h>
25 #include <gui/BufferQueue.h>
26 #include <gui/GLConsumer.h>
27 #include <gui/IGraphicBufferProducer.h>
28 #include <hardware/gralloc.h>
29 
30 #include <cstdint>
31 
32 #include "EglSurfaceTexture.h"
33 #include "EglUtil.h"
34 
35 namespace android {
36 namespace companion {
37 namespace virtualcamera {
38 namespace {
39 
40 // Maximal number of buffers producer can dequeue without blocking.
41 constexpr int kBufferProducerMaxDequeueBufferCount = 64;
42 
43 class FrameAvailableListenerProxy : public ConsumerBase::FrameAvailableListener {
44  public:
FrameAvailableListenerProxy(const std::function<void ()> & callback)45   FrameAvailableListenerProxy(const std::function<void()>& callback)
46       : mOnFrameAvailableCallback(callback) {
47   }
48 
onFrameAvailable(const BufferItem &)49   virtual void onFrameAvailable(const BufferItem&) override {
50     ALOGV("%s: onFrameAvailable", __func__);
51     mOnFrameAvailableCallback();
52   }
53 
54  private:
55   std::function<void()> mOnFrameAvailableCallback;
56 };
57 
58 }  // namespace
59 
EglSurfaceTexture(const uint32_t width,const uint32_t height)60 EglSurfaceTexture::EglSurfaceTexture(const uint32_t width, const uint32_t height)
61     : mWidth(width), mHeight(height) {
62   glGenTextures(1, &mTextureId);
63   if (checkEglError("EglSurfaceTexture(): glGenTextures")) {
64     ALOGE("Failed to generate texture");
65     return;
66   }
67 
68 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
69   mGlConsumer = sp<GLConsumer>::make(mTextureId, GLConsumer::TEXTURE_EXTERNAL,
70                                      false, false);
71   mGlConsumer->setName(String8("VirtualCameraEglSurfaceTexture"));
72   mGlConsumer->setDefaultBufferSize(mWidth, mHeight);
73   mGlConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_TEXTURE);
74   mGlConsumer->setDefaultBufferFormat(AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420);
75 
76   mSurface = mGlConsumer->getSurface();
77   mSurface->setMaxDequeuedBufferCount(kBufferProducerMaxDequeueBufferCount);
78 #else
79   BufferQueue::createBufferQueue(&mBufferProducer, &mBufferConsumer);
80   // Set max dequeue buffer count for producer to maximal value to prevent
81   // blocking when dequeuing input buffers.
82   mBufferProducer->setMaxDequeuedBufferCount(
83       kBufferProducerMaxDequeueBufferCount);
84   mGlConsumer = sp<GLConsumer>::make(
85       mBufferConsumer, mTextureId, GLConsumer::TEXTURE_EXTERNAL, false, false);
86   mGlConsumer->setName(String8("VirtualCameraEglSurfaceTexture"));
87   mGlConsumer->setDefaultBufferSize(mWidth, mHeight);
88   mGlConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_TEXTURE);
89   mGlConsumer->setDefaultBufferFormat(AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420);
90 
91   mSurface = sp<Surface>::make(mBufferProducer);
92 #endif  // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
93 }
94 
~EglSurfaceTexture()95 EglSurfaceTexture::~EglSurfaceTexture() {
96   if (mTextureId != 0) {
97     glDeleteTextures(1, &mTextureId);
98   }
99 }
100 
getSurface()101 sp<Surface> EglSurfaceTexture::getSurface() {
102   return mSurface;
103 }
104 
getCurrentBuffer()105 sp<GraphicBuffer> EglSurfaceTexture::getCurrentBuffer() {
106   return mGlConsumer->getCurrentBuffer();
107 }
108 
setFrameAvailableListener(const std::function<void ()> & listener)109 void EglSurfaceTexture::setFrameAvailableListener(
110     const std::function<void()>& listener) {
111   mFrameAvailableListener =
112       sp<FrameAvailableListenerProxy>::make([this, listener]() {
113         mIsFirstFrameDrawn.store(true);
114         listener();
115       });
116   mGlConsumer->setFrameAvailableListener(mFrameAvailableListener);
117 }
118 
waitForNextFrame(const std::chrono::nanoseconds timeout)119 bool EglSurfaceTexture::waitForNextFrame(const std::chrono::nanoseconds timeout) {
120   return mSurface->waitForNextFrame(mGlConsumer->getFrameNumber(),
121                                     static_cast<nsecs_t>(timeout.count()));
122 }
123 
getTimestamp()124 std::chrono::nanoseconds EglSurfaceTexture::getTimestamp() {
125   return std::chrono::nanoseconds(mGlConsumer->getTimestamp());
126 }
127 
isFirstFrameDrawn()128 bool EglSurfaceTexture::isFirstFrameDrawn() {
129   return mIsFirstFrameDrawn.load();
130 }
131 
updateTexture()132 GLuint EglSurfaceTexture::updateTexture() {
133   int previousFrameId;
134   int framesAdvance = 0;
135   // Consume buffers one at the time.
136   // Contrary to the code comments in GLConsumer, the GLConsumer acquires
137   // next queued buffer (not the most recently queued buffer).
138   while (true) {
139     previousFrameId = mGlConsumer->getFrameNumber();
140     mGlConsumer->updateTexImage();
141     int currentFrameId = mGlConsumer->getFrameNumber();
142     if (previousFrameId == currentFrameId) {
143       // Frame number didn't change after updating the texture,
144       // this means we're at the end of the queue and current attached
145       // buffer is the most recent buffer.
146       break;
147     }
148 
149     framesAdvance++;
150     previousFrameId = currentFrameId;
151   }
152   ALOGV("%s: Advanced %d frames", __func__, framesAdvance);
153   return mTextureId;
154 }
155 
getTextureId() const156 GLuint EglSurfaceTexture::getTextureId() const {
157   return mTextureId;
158 }
159 
getTransformMatrix()160 std::array<float, 16> EglSurfaceTexture::getTransformMatrix() {
161   std::array<float, 16> matrix;
162   mGlConsumer->getTransformMatrix(matrix.data());
163   return matrix;
164 }
165 
getWidth() const166 uint32_t EglSurfaceTexture::getWidth() const {
167   return mWidth;
168 }
169 
getHeight() const170 uint32_t EglSurfaceTexture::getHeight() const {
171   return mHeight;
172 }
173 
174 }  // namespace virtualcamera
175 }  // namespace companion
176 }  // namespace android
177