blob: 98bf62ab9e2454f2b74626cb7ed497698f5dc92c [file] [log] [blame]
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +01001/*
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
Jan Sebechlebskyb8282672024-05-22 10:43:37 +020018#include "utils/Timers.h"
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010019#define LOG_TAG "EglSurfaceTexture"
20
Jim Shargo2e0202f2024-07-30 19:54:43 +000021#include <GLES/gl.h>
22#include <com_android_graphics_libgui_flags.h>
23#include <gui/BufferQueue.h>
24#include <gui/GLConsumer.h>
25#include <gui/IGraphicBufferProducer.h>
26#include <hardware/gralloc.h>
27
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010028#include <cstdint>
29
30#include "EglSurfaceTexture.h"
31#include "EglUtil.h"
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010032
33namespace android {
34namespace companion {
35namespace virtualcamera {
Jan Sebechlebsky759f0a82024-07-02 15:33:16 +020036namespace {
37
38// Maximal number of buffers producer can dequeue without blocking.
39constexpr int kBufferProducerMaxDequeueBufferCount = 64;
40
41} // namespace
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010042
43EglSurfaceTexture::EglSurfaceTexture(const uint32_t width, const uint32_t height)
44 : mWidth(width), mHeight(height) {
45 glGenTextures(1, &mTextureId);
46 if (checkEglError("EglSurfaceTexture(): glGenTextures")) {
47 ALOGE("Failed to generate texture");
48 return;
49 }
Jim Shargo2e0202f2024-07-30 19:54:43 +000050
51#if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
52 mGlConsumer = sp<GLConsumer>::make(mTextureId, GLConsumer::TEXTURE_EXTERNAL,
53 false, false);
54 mGlConsumer->setName(String8("VirtualCameraEglSurfaceTexture"));
55 mGlConsumer->setDefaultBufferSize(mWidth, mHeight);
56 mGlConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_TEXTURE);
57 mGlConsumer->setDefaultBufferFormat(AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420);
58
59 mSurface = mGlConsumer->getSurface();
60 mSurface->setMaxDequeuedBufferCount(kBufferProducerMaxDequeueBufferCount);
61#else
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010062 BufferQueue::createBufferQueue(&mBufferProducer, &mBufferConsumer);
Jan Sebechlebsky759f0a82024-07-02 15:33:16 +020063 // Set max dequeue buffer count for producer to maximal value to prevent
64 // blocking when dequeuing input buffers.
65 mBufferProducer->setMaxDequeuedBufferCount(
66 kBufferProducerMaxDequeueBufferCount);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010067 mGlConsumer = sp<GLConsumer>::make(
68 mBufferConsumer, mTextureId, GLConsumer::TEXTURE_EXTERNAL, false, false);
69 mGlConsumer->setName(String8("VirtualCameraEglSurfaceTexture"));
70 mGlConsumer->setDefaultBufferSize(mWidth, mHeight);
71 mGlConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_TEXTURE);
72 mGlConsumer->setDefaultBufferFormat(AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420);
73
74 mSurface = sp<Surface>::make(mBufferProducer);
Jim Shargo2e0202f2024-07-30 19:54:43 +000075#endif // COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010076}
77
78EglSurfaceTexture::~EglSurfaceTexture() {
79 if (mTextureId != 0) {
80 glDeleteTextures(1, &mTextureId);
81 }
82}
83
84sp<Surface> EglSurfaceTexture::getSurface() {
85 return mSurface;
86}
87
88sp<GraphicBuffer> EglSurfaceTexture::getCurrentBuffer() {
89 return mGlConsumer->getCurrentBuffer();
90}
91
Jan Sebechlebsky18ac32c2024-06-07 09:53:53 +020092void EglSurfaceTexture::setFrameAvailableListener(
93 const wp<ConsumerBase::FrameAvailableListener>& listener) {
94 mGlConsumer->setFrameAvailableListener(listener);
95}
96
Jan Sebechlebskyb8282672024-05-22 10:43:37 +020097bool EglSurfaceTexture::waitForNextFrame(const std::chrono::nanoseconds timeout) {
98 return mSurface->waitForNextFrame(mGlConsumer->getFrameNumber(),
99 static_cast<nsecs_t>(timeout.count()));
100}
101
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100102GLuint EglSurfaceTexture::updateTexture() {
Jan Sebechlebsky759f0a82024-07-02 15:33:16 +0200103 int previousFrameId;
104 int framesAdvance = 0;
105 // Consume buffers one at the time.
106 // Contrary to the code comments in GLConsumer, the GLConsumer acquires
107 // next queued buffer (not the most recently queued buffer).
108 while (true) {
109 previousFrameId = mGlConsumer->getFrameNumber();
110 mGlConsumer->updateTexImage();
111 int currentFrameId = mGlConsumer->getFrameNumber();
112 if (previousFrameId == currentFrameId) {
113 // Frame number didn't change after updating the texture,
114 // this means we're at the end of the queue and current attached
115 // buffer is the most recent buffer.
116 break;
117 }
118
119 framesAdvance++;
120 previousFrameId = currentFrameId;
121 }
122 ALOGV("%s: Advanced %d frames", __func__, framesAdvance);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100123 return mTextureId;
124}
125
Jan Sebechlebsky99492e32023-12-20 09:49:45 +0100126GLuint EglSurfaceTexture::getTextureId() const {
127 return mTextureId;
128}
129
130std::array<float, 16> EglSurfaceTexture::getTransformMatrix() {
131 std::array<float, 16> matrix;
132 mGlConsumer->getTransformMatrix(matrix.data());
133 return matrix;
134}
135
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100136uint32_t EglSurfaceTexture::getWidth() const {
137 return mWidth;
138}
139
140uint32_t EglSurfaceTexture::getHeight() const {
141 return mHeight;
142}
143
144} // namespace virtualcamera
145} // namespace companion
146} // namespace android