blob: 465531b48a28fd8940acaf9e2be3e6e1c9722c77 [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
21#include <cstdint>
22
23#include "EglSurfaceTexture.h"
24#include "EglUtil.h"
25#include "GLES/gl.h"
26#include "gui/BufferQueue.h"
27#include "gui/GLConsumer.h"
28#include "gui/IGraphicBufferProducer.h"
29#include "hardware/gralloc.h"
30
31namespace android {
32namespace companion {
33namespace virtualcamera {
Jan Sebechlebsky759f0a82024-07-02 15:33:16 +020034namespace {
35
36// Maximal number of buffers producer can dequeue without blocking.
37constexpr int kBufferProducerMaxDequeueBufferCount = 64;
38
39} // namespace
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010040
41EglSurfaceTexture::EglSurfaceTexture(const uint32_t width, const uint32_t height)
42 : mWidth(width), mHeight(height) {
43 glGenTextures(1, &mTextureId);
44 if (checkEglError("EglSurfaceTexture(): glGenTextures")) {
45 ALOGE("Failed to generate texture");
46 return;
47 }
48 BufferQueue::createBufferQueue(&mBufferProducer, &mBufferConsumer);
Jan Sebechlebsky759f0a82024-07-02 15:33:16 +020049 // Set max dequeue buffer count for producer to maximal value to prevent
50 // blocking when dequeuing input buffers.
51 mBufferProducer->setMaxDequeuedBufferCount(
52 kBufferProducerMaxDequeueBufferCount);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010053 mGlConsumer = sp<GLConsumer>::make(
54 mBufferConsumer, mTextureId, GLConsumer::TEXTURE_EXTERNAL, false, false);
55 mGlConsumer->setName(String8("VirtualCameraEglSurfaceTexture"));
56 mGlConsumer->setDefaultBufferSize(mWidth, mHeight);
57 mGlConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_TEXTURE);
58 mGlConsumer->setDefaultBufferFormat(AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_420);
59
60 mSurface = sp<Surface>::make(mBufferProducer);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010061}
62
63EglSurfaceTexture::~EglSurfaceTexture() {
64 if (mTextureId != 0) {
65 glDeleteTextures(1, &mTextureId);
66 }
67}
68
69sp<Surface> EglSurfaceTexture::getSurface() {
70 return mSurface;
71}
72
73sp<GraphicBuffer> EglSurfaceTexture::getCurrentBuffer() {
74 return mGlConsumer->getCurrentBuffer();
75}
76
Jan Sebechlebsky18ac32c2024-06-07 09:53:53 +020077void EglSurfaceTexture::setFrameAvailableListener(
78 const wp<ConsumerBase::FrameAvailableListener>& listener) {
79 mGlConsumer->setFrameAvailableListener(listener);
80}
81
Jan Sebechlebskyb8282672024-05-22 10:43:37 +020082bool EglSurfaceTexture::waitForNextFrame(const std::chrono::nanoseconds timeout) {
83 return mSurface->waitForNextFrame(mGlConsumer->getFrameNumber(),
84 static_cast<nsecs_t>(timeout.count()));
85}
86
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +010087GLuint EglSurfaceTexture::updateTexture() {
Jan Sebechlebsky759f0a82024-07-02 15:33:16 +020088 int previousFrameId;
89 int framesAdvance = 0;
90 // Consume buffers one at the time.
91 // Contrary to the code comments in GLConsumer, the GLConsumer acquires
92 // next queued buffer (not the most recently queued buffer).
93 while (true) {
94 previousFrameId = mGlConsumer->getFrameNumber();
95 mGlConsumer->updateTexImage();
96 int currentFrameId = mGlConsumer->getFrameNumber();
97 if (previousFrameId == currentFrameId) {
98 // Frame number didn't change after updating the texture,
99 // this means we're at the end of the queue and current attached
100 // buffer is the most recent buffer.
101 break;
102 }
103
104 framesAdvance++;
105 previousFrameId = currentFrameId;
106 }
107 ALOGV("%s: Advanced %d frames", __func__, framesAdvance);
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100108 return mTextureId;
109}
110
Jan Sebechlebsky99492e32023-12-20 09:49:45 +0100111GLuint EglSurfaceTexture::getTextureId() const {
112 return mTextureId;
113}
114
115std::array<float, 16> EglSurfaceTexture::getTransformMatrix() {
116 std::array<float, 16> matrix;
117 mGlConsumer->getTransformMatrix(matrix.data());
118 return matrix;
119}
120
Jan Sebechlebsky5cb39962023-11-22 17:33:07 +0100121uint32_t EglSurfaceTexture::getWidth() const {
122 return mWidth;
123}
124
125uint32_t EglSurfaceTexture::getHeight() const {
126 return mHeight;
127}
128
129} // namespace virtualcamera
130} // namespace companion
131} // namespace android