Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 759f0a85 authored by Jan Sebechlebsky's avatar Jan Sebechlebsky Committed by Ján Sebechlebský
Browse files

Fix buffer producer being blocked when dequeing buffers.

This cl fixes 2 problems:
 * Despite being documented otherwise, GLConsumer::updateTexImage
   doesn't actually acquire most recently queued buffer, but next
   buffer. This cl modifies EglSurfaceTexture::updateTexture to
   call GLConsumer::updateTexImage repeatedly to actually get
   to most recent buffer.
 * By default the buffer producer allows to dequeue only 1 buffer,
   this cl modifies the limit to maximum of 64, allowing to utilize
   maximal size of buffer queue.

Bug: 349794105
Test: manually with glasses core and benchmarking app
Test: atest virtual_camera_tests CtsVirtualDevicesCameraTestCases CtsVirtualDevicesCameraCtsTestCases
Flag: EXEMPT bugfix
Change-Id: I85c1cba682ea29d5b0ad51ea258a76e2cab06f5f
parent c961ed17
Loading
Loading
Loading
Loading
+30 −1
Original line number Diff line number Diff line
@@ -31,6 +31,12 @@
namespace android {
namespace companion {
namespace virtualcamera {
namespace {

// Maximal number of buffers producer can dequeue without blocking.
constexpr int kBufferProducerMaxDequeueBufferCount = 64;

}  // namespace

EglSurfaceTexture::EglSurfaceTexture(const uint32_t width, const uint32_t height)
    : mWidth(width), mHeight(height) {
@@ -40,6 +46,10 @@ EglSurfaceTexture::EglSurfaceTexture(const uint32_t width, const uint32_t height
    return;
  }
  BufferQueue::createBufferQueue(&mBufferProducer, &mBufferConsumer);
  // Set max dequeue buffer count for producer to maximal value to prevent
  // blocking when dequeuing input buffers.
  mBufferProducer->setMaxDequeuedBufferCount(
      kBufferProducerMaxDequeueBufferCount);
  mGlConsumer = sp<GLConsumer>::make(
      mBufferConsumer, mTextureId, GLConsumer::TEXTURE_EXTERNAL, false, false);
  mGlConsumer->setName(String8("VirtualCameraEglSurfaceTexture"));
@@ -75,7 +85,26 @@ bool EglSurfaceTexture::waitForNextFrame(const std::chrono::nanoseconds timeout)
}

GLuint EglSurfaceTexture::updateTexture() {
  int previousFrameId;
  int framesAdvance = 0;
  // Consume buffers one at the time.
  // Contrary to the code comments in GLConsumer, the GLConsumer acquires
  // next queued buffer (not the most recently queued buffer).
  while (true) {
    previousFrameId = mGlConsumer->getFrameNumber();
    mGlConsumer->updateTexImage();
    int currentFrameId = mGlConsumer->getFrameNumber();
    if (previousFrameId == currentFrameId) {
      // Frame number didn't change after updating the texture,
      // this means we're at the end of the queue and current attached
      // buffer is the most recent buffer.
      break;
    }

    framesAdvance++;
    previousFrameId = currentFrameId;
  }
  ALOGV("%s: Advanced %d frames", __func__, framesAdvance);
  return mTextureId;
}